Post

(코딩 자율학습 스프링 부트3) 12장


서비스와 트랜잭션의 개념

서비스란 컨트롤러와 리파지터리 사이에 위치하는 계층으로, 서버의 핵심 기능(비지니스 로직)을 처리하는 순서를 총괄한다 모두 성공해야 하는 일련의 과정을 트랜잭션이라고 하며 트랜잭션이 실패로 돌아갈 경우 진행 초기 단계로 돌리는 것을 롤백이라고 한다

서비스 계층 만들기

서비스 계층을 추가해서 컨트롤러, 서비스, 리파지터리의 역할을 분업해보도록 한다

[기존의 컨트롤러에서 서비스와 분업하게 변경됨 –11장 참고]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
// FirstApiController 파일

@GetMapping("/api/articles")
public List<Article> index() {
//        return articleRepository.findAll();
return articleService.index();
}

@GetMapping("/api/articles/{id}")
public Article show(@PathVariable Long id) {
//        return articleRepository.findById(id).orElse(null);
return articleService.show(id);
}

// POST
@PostMapping("/api/articles")
public ResponseEntity<Article> create(@RequestBody ArticleForm dto) {
//    public Article create(@RequestBody ArticleForm dto) {
//        Article article = dto.toEntity();
//        return articleRepository.save(article);
Article created = articleService.create(dto);
return (created != null) ? // 생성하면 정상, 실패하면 오류 응답
ResponseEntity.status(HttpStatus.OK).body(created) :
ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
}

// PATCH
@PatchMapping("/api/articles/{id}")
public ResponseEntity<Article> update(@PathVariable Long id, @RequestBody ArticleForm dto) {
Article updated = articleService.update(id, dto);
return (updated != null) ?
ResponseEntity.status(HttpStatus.OK).body(updated) :
ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
}

//    //DELETE
@DeleteMapping("/api/articles/{id}")
public ResponseEntity<Article> delete(@PathVariable Long id) {
Article deleted = articleService.delete(id);
return (deleted != null) ?
ResponseEntity.status(HttpStatus.NO_CONTENT).build() :
ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
}

[서비스를 생성하여 기존의 컨트롤러에서 처리한 부분을 서비스가 처리]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// 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(); // dto를 엔티티로 변환한후 article에 저장
if(article.getId()!=null){
return null;
}
return articleRepository.save(article); // article을 db에 저장
}

public Article update(Long id, ArticleForm dto) {
// 1. DTO -> 엔티티 변환하기
Article article = dto.toEntity();
log.info("id: {}, article: {}", id, article.toString());
// 2. 타깃 조회하기
Article target = articleRepository.findById(id).orElse(null);
// 3. 잘못된 요청 처리하기
if (target == null || id != article.getId()){
//400. 잘못된 요청 응답!
log.info("잘못된 요청! id:{}, article:{}",id,article.toString());
return null;
}
// 4. 업데이트 및 정상 응답(200)하기
// 기존 데이터에 새 데이터 붙이기
target.patch(article);
Article updated = articleRepository.save(article);
return updated;
}

public Article delete(Long id) {
// 1. 대상 찾기
Article target = articleRepository.findById(id).orElse(null);
// 2. 잘못된 요청 처리하기
if(target == null){
return null;
}
// 3. 대상 삭제하기
articleRepository.delete(target);
return target;
}

ResponseEntity란

Spring Framework에서 제공하는 클래스 중 HttpEntity라는 클래스가 존재한다. 이것은 HTTP 요청(Request) 또는 응답(Response)에 해당하는 HttpHeader와 HttpBody를 포함하는 클래스이다

[HttpEntity 클래스]

1
2
3
4
5
6
7
8
9
public class HttpEntity<T> {

private final HttpHeaders headers;

@Nullable
private final T body;

}

[HttpEntity 클래스를 상속받은 클래스들]

HttpEntity 클래스를 상속받아 구현한 클래스가 RequestEntity, ResponseEntity 클래스이다. ResponseEntity는 사용자의 HttpRequest에 대한 응답 데이터를 포함하는 클래스이다. 따라서 HttpStatus, HttpHeaders, HttpBody를 포함한다

1
2
3
4
public class RequestEntity<T> extends HttpEntity<T>
public class ResponseEntity<T> extends HttpEntity<T>

This post is licensed under CC BY 4.0 by the author.