이번 글은 외래키를 가진 Post 엔티티의 전체 조회와 상세 조회를 구현한 글입니다.
전체 조회 API는 모든 회원의 글 전체를 조회할 수 있고, 특정 회원의 글 전체를 조회할 수 있습니다.
1. 게시글 목록 기능 구현
- issues #41
- Pull request #53 - 해당 링크로 코드를 확인할 수 있습니다
1. Response DTO
반환할 DTO를 생성한다.
@Getter
public class PostResponseDto {
private String title;
private String content;
private String userName;
private LocalDateTime createdAt;
}
2. PostController
@GetMapping
public List<PostResponseDto> getPosts(@RequestParam(value = "userpk", required = false) Long userPk) {
return postMinjService.getPosts(userPk);
}
List<PostResponseDto>
- 게시글 목록을 반환하는 것이므로 List로 반환한다.
@RequestParam(value = "userpk", required = false) Long userPk
- userpk를 파라미터로 받기 위한 어노테이션이다.
- 해당 파라미터를 상황에 따라 안 받을 수도 있어 required를 false로 주었다.
- 타입이 long일 경우 null값을 허용하지 못한다. 그래서 Long타입으로 받는다
3. PostService
public List<PostResponseDto> getPosts(Long userPk) {
return userMinjRepository.getPosts(userPk);
}
Post 엔티티에 해당하는 리포지토리가 있지만 목록 기능은 queryDSL을 사용하여 구현할 것이다.
그래서 QueryDSL이 세팅되어 있는 User 리포지토리에서 작업을 했다.
아무런 조건 없이 리스트를 반환할 때 예외 처리를 해야할까?
게시글 전체 조회 API에서는 userPk가 존재하는지 체크하지 않는다.
내가 어떤 웹사이트에서 무엇을 검색했는데 그 값이 없다고 오류를 던지는 사이트를 본 적이 있는지 생각해보자.
목록 리스트는 있는 대로 보여주고 없으면 없는 리스트를 반환해준다.
리스트가 비었을 때의 처리는 해당 API를 사용하는 클라이언트가 처리할 부분이다.
4. UserRepositoryImpl
entity > user > repository > UserRepositoryExtension.java
List<PostResponseDto> getPosts(Long userPk);
해당 인터페이스에서 메소드를 선언해준다.
entity > user > repository > UserRepositoryImpl.java
@Override
public List<PostResponseDto> getPosts(Long userPk) {
return queryFactory
.select(Projections.fields(
PostResponseDto.class,
postMinj.postTitle.as("title"),
postMinj.postContent.as("content"),
postMinj.userMinj.userName,
postMinj.createdAt))
.from(postMinj)
.where(userPkEq(userPk))
.orderBy(postMinj.createdAt.desc())
.fetch();
}
private BooleanExpression userPkEq(Long userPk) {
return userPk != null ? userMinj.id.eq(userPk) : null;
}
해당 클래스에서 메소드를 오버라이딩한다.
Projections.fields(PostResponseDto.class, ...)
- 엔티티와 반환 타입이 다를 경우 필드에 직접 접근하는 메소드이다.
- 접근할 DTO와 필드를 순서에 상관없이 적어준다.
- 생성자와 달리 필드에 직접 접근하는 거라 이름이 매칭되어야 한다.
postMinj.postTitle.as("title")
- 이름이 매칭되어야 하는데, 엔티티와 DTO 필드 이름이 다를 경우 as를 사용한다.
- entity필드.as(”DTO필드”)
userPkEq(userPk)
- null 체크를 하는 메소드이다.
- eq를 사용하여 where문을 작성할 수 있는데, 변수가 null일 경우 해당 where문을 무시한다.
fetch()
- 결과를 List로 반환하는 메소드이다.
Projections
을 사용할 경우 반환형이JPQLQuery
가 되어 사용해주어야 한다.
실행 결과
- 전체 조회
- 유저에 해당하는 게시글 전체 조회
2. 게시글 상세 조회 기능 구현
1. PostController
@PostMapping("/details/{id}")
public PostResponseDto getPost(@PathVariable(name="id") @Valid long postId){
return postMinjService.getPost(postId);
}
@PathVariable(name="id") @Valid long postId
- 변수의 값을 파라미터로 받을 때 사용하는 어노테이션이다. name으로 경로 변수를 받고 파라미터에서는 따로 이름을 작성할 수 있다.
2. PostService
public PostResponseDto getPost(long postId){
PostMinj postMinj = postRepository.findById(postId).orElseThrow(() -> {
throw new ApiExceptionMinJ(ErrorCodeEnum.POST_NOT_FOUND);
});
return PostResponseDto.of(postMinj);
}
postRepository.findById(postId).orElseThrow()
- postId에 해당하는 게시글이 있는지 찾고 해당 엔티티를 저장한다.
dto > response > PostResponseDto.java
@Getter
public class PostResponseDto {
private long id;
private String title;
private String content;
private String userName;
private LocalDateTime createdAt;
public static PostResponseDto of(PostMinj postMinj){
PostResponseDto postResponseDto = new PostResponseDto();
postResponseDto.id = postMinj.getId();
postResponseDto.title = postMinj.getPostTitle();
postResponseDto.content = postMinj.getPostContent();
postResponseDto.userName = postMinj.getUserMinj().getUserName();
postResponseDto.createdAt = postMinj.getCreatedAt();
return postResponseDto;
}
}
DTO를 생성해주는 정적 메소드를 만든다.
실행 결과
'Study > Spring' 카테고리의 다른 글
@Query로 update문 작성하기 | Spring Spring boot JPA 쿼리 어노테이션 (0) | 2022.04.27 |
---|---|
User 엔티티를 외래키로 가진 Post 엔티티 추가하기(INSERT) | Spring Spring boot JPA Study (0) | 2022.02.16 |
JPA Auditing 사용하여 엔티티 설계하기 | Spring Spring boot JPA Study (0) | 2022.02.15 |
Controller 통합 테스트 코드 | Spring Spring boot JPA Study (0) | 2022.02.12 |
[Spring | test | H2] test에서 H2 DB 연결하기 (0) | 2022.02.12 |
댓글