[SpringBoot] 스프링부트 + JPA를 이용한 CRUD 구현 3. 등록 기능 만들기
🎋 Controller
src/main/java/com/test/spring/boot_crud/web/PostsApiController.java
package com.test.spring.boot_crud.web;
import com.test.spring.boot_crud.service.posts.PostsService;
import com.test.spring.boot_crud.web.dto.PostsSaveRequestDto;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RequiredArgsConstructor
@RestController
public class PostsApiController {
private final PostsService postsService;
@PostMapping("/api/posts")
public Long save(@RequestBody PostsSaveRequestDto requestDto) {
return postsService.save(requestDto);
}
}
-
@RequiredArgsConstructor : 의존성 주입(Dependency Injection) 활용을 위해 사용 / final 필드나 @NotNull이 붙은 모든 필드에 대해 생성자를 생성해준다.
-
@RestController : @Controller + @ResponseBody / Controller 클래스에 @RestController 어노테이션을 붙이면 하위 메서드 마다 @ResponseBody를 추가하지 않아도 객체를 문자열이나 JSON의 형태로 전송할 수 있다.
-
@RequestBody : HTTP 요청의 Body 내용을 통째로 자바 객체로 변환해 매핑된 메소드의 파라미터로 전달
- @ResponseBody : 자바 객체를 HTTP 요청의 Body 내용으로 매핑하여 클라이언트로 전송
🎋 Service
src/main/java/com/test/spring/boot_crud/service/PostsService.java
package com.test.spring.boot_crud.service.posts;
import com.test.spring.boot_crud.domain.posts.PostsRepository;
import com.test.spring.boot_crud.web.dto.PostsSaveRequestDto;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@RequiredArgsConstructor
@Service
public class PostsService {
private final PostsRepository postsRepository;
@Transactional
public Long save(PostsSaveRequestDto requestDto) {
return postsRepository.save(requestDto.toEntity()).getId();
}
}
-
@Transactional
-
클래스 또는 메서드에 선언, 빈 생성 시 프록시로 생성하여 호출될 때 트랜잭션 처리를 진행
-
Transaction의
begin
과commit
을 메인 로직 앞뒤로 수행, 예외 발생 시rollback
처리를 자동으로 해주는 기능을 담당 -
Proxy 형태로 동작 > 외부에서 접근이 가능한 메서드만 설정 가능 (private 적용 시 오류 발생)
-
-
.save() : 파라미터로 들어온 entity가 새로운 엔터티라면
insert
, 이미 존재하는 엔터티라면update
🎋 Dto
src/main/java/com/test/spring/boot_crud/web/dto/PostsSaveRequestDto.java
package com.test.spring.boot_crud.web.dto;
import com.test.spring.boot_crud.domain.posts.Posts;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
@Getter
@NoArgsConstructor
public class PostsSaveRequestDto {
private String title;
private String content;
private String author;
@Builder
public PostsSaveRequestDto(String title, String content, String author) {
this.title = title;
this.content = content;
this.author = author;
}
public Posts toEntity(){
return Posts.builder()
.title(title)
.content(content)
.author(author)
.build();
}
}
🎋 등록 페이지
src/main/resources/templates/posts-save.mustache
<h1>게시글 등록</h1>
<div class="col-md-8">
<div class="col-md-6">
<form>
<div class="form-group">
<label for="title">제목</label>
<input type="text" class="form-control" id="title" placeholder="제목을 입력하세요.">
</div>
<div class="form-group">
<label for="author">작성자</label>
<input type="text" class="form-control" id="author" placeholder="작성자를 입력하세요.">
</div>
<div class="form-group">
<label for="content">내용</label>
<input type="text" class="form-control" id="content" placeholder="내용을 입력하세요.">
</div>
</form>
<br>
<div class="btn-group" role="group" aria-label="btns">
<a href="/" role="button"><button type="button" class="btn btn-secondary">취소</button></a>
<button type="button" class="btn btn-warning" id="btn-save">등록</button>
</div>
</div>
</div>
🎋 index.js
src/resources/static/js/app/index.js
var main = {
init : function(){
var _this = this;
$('#btn-save').on('click', function(){
_this.save();
});
},
save : function(){
var data = {
title: $('#title').val(),
author: $('#author').val(),
content: $('#content').val()
};
$.ajax({
type: 'POST',
url: '/api/posts',
dataType: 'json',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify(data)
}).done(function(){
alert('게시글이 등록되었습니다.');
window.location.href = '/';
}).fail(function(error){
alert(JSON.stringify(error));
});
}
};
main.init();
footer.mustache에 index.js를 추가해주자.
<script src=...
...>
<script src="/js/app/index.js"></script>
</body>
</html>
🎋 Controller
src/main/java/com/test/spring/boot_crud/web/IndexController.java
package com.test.spring.boot_crud.web;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class IndexController {
@GetMapping("/")
public String index() {
return "index";
}
@GetMapping("/posts/save")
public String postsSave(){
return "posts-save";
}
}