ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Dto로 프로젝션 결과 반환
    JPA/Querydsl 2023. 8. 13. 14:55
    @Test
    public void findDtoByJPQL() {
        List<MemberDto> result = em.createQuery("select new study.querydsl.dto.MemberDto(m.username, m.age) from Member m", MemberDto.class)
                .getResultList();
    
        for (MemberDto memberDto : result) {
            System.out.println("memberDto = " + memberDto);
        }
    }

    JPQL을 이용해서 Dto로 결과를 반환하려면 new 명령어를 사용해서 패키지명을 전부 다 입력해줘야지 Dto로 받아올 수 있었다.

     

     

     

    Querydsl의 빈 생성

    • 프러퍼티 접근
    • 필드 직접 접근
    • 생성자 사용

     

     

    1. 프로퍼티 접근

    @Test
    public void findDtoBySetter() {
        List<MemberDto> result = queryFactory
                .select(Projections.bean(MemberDto.class, member.username, member.age))
                // Projections.bean(Dto 클래스, member.변수, member.변수)
                .from(member)
                .fetch();
    
        for (MemberDto memberDto : result) {
            System.out.println(memberDto);
        }
    }

    프로퍼티 접근(bean)은 Dto에 있는 setter를 통해서 값이 생성되는 방식이다.

     

     

     

     

    2. 필트 활용 방법

    @Test
    public void findDtoByField() {
        List<MemberDto> result = queryFactory
                .select(Projections.fields(MemberDto.class, member.username, member.age))
                // Projections.fields(Dto 클래스, member.변수, member.변수)
                .from(member)
                .fetch();
    
        for (MemberDto memberDto : result) {
            System.out.println(memberDto);
        }
    }

    위에서 bean()을 fileds()로 바꿔준거 말고는 차이가 없는데 위에서는 setter를 이용해서 넣었는데 이번에는 그냥 필드에 주입시키는 것이다.

     

     

     

    3. 생성자 사용

    @Test
    public void findDtoByConstructor() {
        List<MemberDto> result = queryFactory
                .select(Projections.constructor(MemberDto.class, member.username, member.age))
                // Projections.constructor(Dto 클래스, member.변수, member.변수)
                .from(member)
                .fetch();
    
        for (MemberDto memberDto : result) {
            System.out.println(memberDto);
        }
    }

    construcotr는 생성자를 사용하는 것인데, MemberDto 클래스의 타입과 변수 순서가 일치해야 한다.

     

     

     

     

    4. @QueryProjection

    @Data
    @NoArgsConstructor
    public class MemberDto {
    
        private String username;
        private int age;
    
        @QueryProjection
        public MemberDto(String username, int age) {
            this.username = username;
            this.age = age;
        }
    }

    MemberDto의 생성자에 @QueryProjection을 넣어주면 QMemberDto가 생긴다.

    별도의 QMemberDto가 생김

     

     

     

    장점

    @Test
    public void findDtoByQueryProjection() {
        List<MemberDto> result = queryFactory
                .select(new QMemberDto(member.username, member.age))
                .from(member)
                .fetch();
    }

    이러한 방식의 장점은 생성자를 만들 때 필요한 것들만 주입할 수 있다는 것이다. new QMemberDto(member.username, member.age, member.key)라고 입력하면 컴파일 에러가 생긴다.

    위의 경우에서는 이렇게 입력해도 런타임 에러가 생기는데, @QueryProjection은 컴파일 시점에 잡아준다는 장점이 있다.

     

     

     

     

     

    단점

    하지만 Q파일을 별도로 만들어야한다는 단점이 있고, Dto 계층에서 @QueryProjection을 사용하기 때문에 Dto에서도 querydsl의 기능이 들어가는 아키텍쳐 상 문제가 생긴다는 단점이 있다.

     

     

     

    4가지 방식의 장단점을 판단해서 필요한 기능을 사용하면 된다.

    'JPA > Querydsl' 카테고리의 다른 글

    Querydsl의 수정, 삭제 쿼리  (0) 2023.08.13
    Querydsl의 동적 쿼리  (0) 2023.08.13
    Querydsl - Case 문  (0) 2023.08.13
    Querydsl - 서브 쿼리  (0) 2023.08.13
    Querydsl - 조인  (0) 2023.08.13
Designed by Tistory.