JPA/실전! Querydsl

프로젝션과 결과 반환 DTO 조회 (JPA VS Querydsl)

동구나라 2022. 10. 11. 21:05
순수 JPA에서 DTO조회


MemberDto

package study.querydsl.dto;

import lombok.Data;

@Data
public class MemberDto {
    private String username;
    private int age;


    public MemberDto(String username, int age) {
        this.username = username;
        this.age = age;
    }
}



@Test

@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);
    }
}

단점

  • 순수 JPA에서 DTO를 조회할 때는 new 명령어를 사용해야함
  • DTO의 package 이름을 다 적워줘야해서 지저분함
  • 생성자 방식만 지원함
new study.querydsl.dto.MemberDto(m.username, m.age)


Querydsl  

Querydsl 빈 생성(Bean population)

결과를 DTO 반환할 때 사용
다음 3가지 방법 지원

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

프로퍼티 접근 - Setter


- Projections.bean을 사용해서 JPA 보다 간단하게 Dto 조회를 함

@Test
public void findDtoBySetter(){
    List<MemberDto> result = queryFactory
            .select(Projections.bean(MemberDto.class,
                    member.username,
                    member.age))
            .from(member)
            .fetch();
    for (MemberDto memberDto : result) {
        System.out.println("memberDto = " + memberDto);
    }
}

필드 직접 접근

- fields 를 사용

@Test
public void findDtoByField(){ //필드 직접 접근
    List<MemberDto> result = queryFactory
            .select(Projections.fields(MemberDto.class,
                    member.username,
                    member.age))
            .from(member)
            .fetch();
    for (MemberDto memberDto : result) {
        System.out.println("memberDto = " + memberDto);
    }
}

생성자 사용

- constructor 사용

@Test
public void findDtoByConstructor(){ //생성자 사용
    List<MemberDto> result = queryFactory
            .select(Projections.constructor(MemberDto.class,
                    member.username,
                    member.age))
            .from(member)
            .fetch();
    for (MemberDto memberDto : result) {
        System.out.println("memberDto = " + memberDto);
    }
}

별칭이 다를 때

- 예제) UserDto 생성해서 username 을 name으로 다르게 설정

@Data
public class UserDto {
    private String name;
    private int age;
}




- member.username . as 사용 ("name")

@Test
public void findUserDto() { //생성자 사용
     QMember memberSub = new QMember("memberSub");
    List<UserDto> result = queryFactory
            .select(Projections.fields(UserDto.class,
                    member.username.as("name"),
                    
                    //서브쿼리
                    ExpressionUtils.as(JPAExpressions
                            .select(memberSub.age.max())
                            .from(memberSub), "age")
                    ))
            .from(member)
            .fetch();
    for (UserDto userDto : result) {
        System.out.println("userDto = " + userDto);
    }
}
  • 프로퍼티나, 필드 접근 생성 방식에서 이름이 다를 때 해결 방안
  • ExpressionUtils.as(source,alias) : 필드나 , 서브 쿼리에 별칭 적용
  • username.as("memberName") : 필드에 별칭 적용

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

Querydsl Case 문  (0) 2022.10.11
querydsl 서브쿼리  (0) 2022.10.11
querydsl 조인 - 기본조인  (0) 2022.10.11
querydsl 정렬  (0) 2022.10.10
결과 조회  (0) 2022.10.10