본문 바로가기
Study/Spring

User 엔티티를 외래키로 가진 Post 엔티티 조회하기 | Spring Spring boot JPA Study

by M개발자 2022. 2. 16.
반응형

이번 글은 외래키를 가진 Post 엔티티의 전체 조회와 상세 조회를 구현한 글입니다.

전체 조회 API는 모든 회원의 글 전체를 조회할 수 있고, 특정 회원의 글 전체를 조회할 수 있습니다. 

 

1. 게시글 목록 기능 구현

 

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를 생성해주는 정적 메소드를 만든다.

 

실행 결과

 


회의록

반응형

댓글