728x90
바로 Service부터 확인해 보자
PostService
package hongxeob.restapi_crud.service;
import hongxeob.restapi_crud.Post;
import hongxeob.restapi_crud.repository.PostRepository;
import hongxeob.restapi_crud.request.CreatePostDto;
import hongxeob.restapi_crud.request.PostConvert;
import hongxeob.restapi_crud.request.UpdatePostDto;
import hongxeob.restapi_crud.response.PostListResponse;
import hongxeob.restapi_crud.response.PostResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;
import java.util.List;
import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor
public class PostService {
private final PostRepository postRepository;
//등록
@Transactional
public void create(@RequestBody CreatePostDto createPostDto) {
Post post = Post.builder()
.title(createPostDto.getTitle())
.content(createPostDto.getContent())
.build();
postRepository.save(post);
}
//한 건 조회
@Transactional(readOnly = true)
public PostResponse findOne(Long id) {
Post findPost = postRepository.findById(id).orElseThrow(() -> new IllegalArgumentException("찾는 게시물이 없습니다 id " + id));
PostResponse response = PostResponse.builder()
.id(findPost.getId())
.title(findPost.getTitle())
.content(findPost.getContent())
.build();
return response;
}
//전체 게시글
@Transactional(readOnly = true)
public PostListResponse findAll() {
List<PostResponse> postResponses = postRepository.findAll().stream().map(PostResponse::new).collect(Collectors.toList());
return PostListResponse.builder().postList(postResponses).build();
}
@Transactional
public void update(Long id, @RequestBody UpdatePostDto updatePostDto) {
Post post = postRepository.findById(id).orElseThrow(() -> new IllegalArgumentException("게시물을 찾을 수 없습니다 id= " + id));
PostConvert postConvert = post.toConvert();
postConvert.setTitle(updatePostDto.getTitle());
postConvert.setContent(updatePostDto.getContent());
post.update(postConvert);
}
@Transactional
public void delete(Long id) {
Post post = postRepository.findById(id).orElseThrow(
() -> new IllegalArgumentException("게시글을 찾을 수 없습니다. id = " + id));
postRepository.deleteById(post.getId());
}
}
게시물 등록
//게시물 등록
@Transactional
public void create(@RequestBody CreatePostDto createPostDto) {
Post post = Post.builder()
.title(createPostDto.getTitle())
.content(createPostDto.getContent())
.build();
postRepository.save(post);
}
- Service 로직은 트랜잭션 단위로 기능들이 수행이 되니 꼭 @Transactional을 붙여주자.
- HTTP Request로 받은 JSON 데이터를 Java 객체에 매핑하기 위해 @RequestBody 어노테이션을 사용했다.
- 생성할 때 요청받은 데이터인 CreatePostDto를 사용
- PostRepository는 Post 형태만 받을 수 있으므로, Post의 빌더 패턴을 사용하여 createPostDto 데이터를 넣어준다.
- Post의 ID는 자동증가 된다. (Post 엔티티의 ID는 IDENTITY 전략!)
게시물 한 건 조회
//한 건 조회
@Transactional(readOnly = true)
public PostResponse findOne(Long id) {
Post findPost = postRepository.findById(id).orElseThrow(() -> new IllegalArgumentException("찾는 게시물이 없습니다 id " + id));
PostResponse response = PostResponse.builder()
.id(findPost.getId())
.title(findPost.getTitle())
.content(findPost.getContent())
.build();
return response;
}
- 데이터를 조회만 하는 것이기 때문에 DB에 변화가 없다 -> 트랜잭션을 readOnly = true로 걸어줘 성능을 향상 시키자.
- 응답은 PostResponse 객체로 받기에 Json 형태로 받을 수 있다.
- 찾는 ID가 없을 수 있으므로, orElseThrow를 사용해 예외를 던져준다.
- ID를 찾을 경우 응답해줄 데이터인 PostResponse의 빌더 패턴을 이용해 해당 형태로 만들어주고 리턴한다.
게시물 전체 조회
//전체 게시글
@Transactional(readOnly = true)
public PostListResponse findAll() {
List<PostResponse> postResponses = postRepository.findAll().stream().map(PostResponse::new).collect(Collectors.toList());
return PostListResponse.builder().postList(postResponses).build();
}
- 게시물 전체 조회는 List로 받을 수 있지만, 이전 글에서도 봤듯이 PostListResponse 객체로 받아준다. (이유는 전글 참조)
- findAll() 메소드로 받으면 타입은 Post 타입이므로, 스트림을 사용해 PostResponseDto로 형변환을 해준다.
- 마지막으로, 받은 List를 PostListResponse의 빌더 패턴을 사용해 PostListResponse 객체로 바꿔서 리턴해 준다.
게시물 수정
//게시물 수정
@Transactional
public void update(Long id, @RequestBody UpdatePostDto updatePostDto) {
Post post = postRepository.findById(id).orElseThrow(() -> new IllegalArgumentException("게시물을 찾을 수 없습니다 id= " + id));
PostConvert postConvert = post.toConvert();
postConvert.setTitle(updatePostDto.getTitle());
postConvert.setContent(updatePostDto.getContent());
post.update(postConvert);
}
- 해당 게시물을 찾아야 하므로 id를 파라미터로 받아 확인한다.
- ID로 찾은 post를 수정하기 위해 toConvert() 메소드를 사용하여 PostConvert로 바꿔준다.
- Post는 setter를 사용할 수 없다!
- 바꿔준 postConvert을 파라미터로 온 updatePostDto의 내용으로 업데이트 해준다 (제목,내용)
- 처음 ID로 찾은 Post 데이터를 update 메소드를 통해 변경한다.
게시물 삭제
@Transactional
public void delete(Long id) {
Post post = postRepository.findById(id).orElseThrow(
() -> new IllegalArgumentException("게시글을 찾을 수 없습니다. id = " + id));
postRepository.deleteById(post.getId());
}
- ID를 통해 삭제할 Post를 찾고 해당 ID를 이용해 삭제 시켜준다
PostController
package hongxeob.restapi_crud.controller;
import hongxeob.restapi_crud.request.CreatePostDto;
import hongxeob.restapi_crud.request.UpdatePostDto;
import hongxeob.restapi_crud.response.PostListResponse;
import hongxeob.restapi_crud.response.PostResponse;
import hongxeob.restapi_crud.service.PostService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
@RestController
@RequiredArgsConstructor
public class PostController {
private final PostService postService;
@PostMapping("/posts")
public void create(@RequestBody CreatePostDto createPostDto) {
postService.create(createPostDto);
}
@GetMapping("/posts")
public PostListResponse findAll() {
return postService.findAll();
}
@GetMapping("/posts/{id}")
public PostResponse findOne(@PathVariable Long id) {
return postService.findOne(id);
}
@PatchMapping("/posts/{id}")
public void update(@PathVariable Long id, @RequestBody UpdatePostDto updatePostDto) {
postService.update(id, updatePostDto);
}
@DeleteMapping("/posts/{id}")
public void delete(@PathVariable Long id) {
postService.delete(id);
}
}
Service 로직을 잘 구현했다면, Controller는 그 Service 로직의 메소드만 잘 사용해주면 된다!
'프로젝트 > RestApi_CRUD' 카테고리의 다른 글
RestApi 게시판 CRUD 연습 (5) - PostMan (0) | 2023.03.16 |
---|---|
RestApi 게시판 CRUD 연습 (4) - 유닛 테스트 : Controller 테스트 with MockMvc (0) | 2023.03.16 |
RestApi 게시판 CRUD 연습 (3) - 유닛 테스트 : Service 테스트 (0) | 2023.03.15 |
RestApi 게시판 CRUD 연습 (1) - 연습 이유 / 프로젝트 세팅 / Entity,DTO,Repository (0) | 2023.03.14 |