👉 Mission. 기존 Article의 Rest API 구현에 Service 계층을 추가하시오.
: Controller와 Repository 사이에 위치하는 계층으로서 처리 업무의 순서를 총괄
트랜잭션(Transaction)
: 모두 성공되어야 하는 일련의 과정
롤백(Rollback)
: 실패 시, 진행 초기 단계로 돌리는 것
그리고 이러한 트랜잭션은 Service 가 관리한다!
실습에 사용되는 어노테이션 설명 👇
@Service
: 해당 클래스를 서비스로 인식하여 스프링 부트에 객체를 생성(등록)@Transactional
: 해당 메서드를 트랜잭션으로 묶는다!Controller 는 클라이언트에게 요청을 받고 응답 처리만 하게끔 Service 를 추가해 코드 변경을 해보자!
파일명 : api/ArticleApiController.java
@Autowired
private ArticleService articleService; //Service 연결
//GET - 전체 article
@GetMapping("/api/articles")
public List<Article> index(){
return articleService.index();
}
//GET - 단일 article
@GetMapping("/api/articles/{id}")
public Article show(@PathVariable Long id){
return articleService.show(id);
}
//POST - 생성
@PostMapping("/api/articles")
public ResponseEntity<Article> create(@RequestBody ArticleForm dto) {
Article created = articleService.create(dto);
return (created != null) ?
ResponseEntity.status(HttpStatus.CREATED).body(created) :
ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
}
//PATCH
@PatchMapping("/api/articles/{id}")
public ResponseEntity<Article> update(@RequestBody ArticleForm dto,
@PathVariable Long id){
Article updated = articleService.update(dto, id);
return (updated != null) ?
ResponseEntity.status(HttpStatus.OK).body(updated):
ResponseEntity.status(HttpStatus.BAD_REQUEST).build(); //OK = 200
}
//DELETE - 삭제
@DeleteMapping("/api/articles/{id}")
public ResponseEntity<Void> delete(@PathVariable Long id){
Article deleted = articleService.delete(id);
return (deleted != null) ?
ResponseEntity.status(HttpStatus.NO_CONTENT).build():
ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
}
Service 구현을 위해 Service 패키지를 생성해주자.
파일명 : Service/ArticleService.java
@Service //서비스 선언! (서비스 객체를 스프링 객체에 생성)
public class ArticleService {
@Autowired
private ArticleRepository articleRepository;
public List<Article> index() {
return articleRepository.findAll();
}
public Article show(Long id) {
return articleRepository.findById(id).orElse(null);
}
public Article create(ArticleForm dto) {
Article article = dto.toEntity();
//POST 요청으로 기존 articlel이 수정되는 것 방지
if(article.getId() != null){
return null;
}
return articleRepository.save(article);
}
public Article update(ArticleForm dto, Long id) {
Article article = dto.toEntity();
Article target = articleRepository.findById(id).orElse(null);
if(target == null || id != article.getId()){
return null;
}
target.patch(article);
return articleRepository.save(target);
}
public Article delete(Long id) {
Article target = articleRepository.findById(id).orElse(null);
if(target == null){
return null;
}
articleRepository.delete(target);
return target;
}
}
1) Service 계층
여태까지는 Controller 에 클라이언트로부터 요청을 받아 모든 처리까지 담당하게 하였으나, Service 계층을 생성하여 역할을 확실하게 배분한다.
2) 트랜잭션과 롤백
어떤 코드를 수행할 때, 해당 메서드가 실행되다가 중간에 에러가 나서 취소가 된다면, 여태까지 수행되는 코드가 다시 전부 취소 즉, '이전 상태로 되돌아가야 (=롤백)' 하지 않겠는가?
그럴 때 사용하는 것이 바로 '트랜잭션' 과 '롤백'이다.
트랜잭션은 원하는 메서드에 @Transactional
어노테이션을 붙여 사용 가능하다.
강의 출처 : https://www.youtube.com/watch?v=_vDACE13Ubc&list=PLyebPLlVYXCiYdYaWRKgCqvnCFrLEANXt&index=1 [스프링 부트 입문 - 홍팍]