BackEnd/Querydsl

08. Querydsl Projection

hanseom 2021. 7. 27. 08:57
반응형

[전체소스코드]

 

1. 프로젝션이란?

  > 프로젝션이란 SELECT 대상 지정을 의미한다. 아래와 같이 프로젝션 대상이 하나인 경우 명확하게 타입을 지정할 수 있으나 프로젝션 대상이 둘 이상이면 튜플(Tuple)이나 DTO로 조회해야 한다.

    List result = queryFactory .select(member.username) .from(member) .fetch();

 

2. Querydsl DTO 반환

  > JPA에서 DTO를 조회할 때는 new 명령어로 package이름을 다 적어주어야 한다. (생성자 방식만 지원)

    em.createQuery("select new com.spring.querydsl.dto.MemberDto(m.username, m.age) from Member m",                                  MemberDto.class).getResultList();

 

  1) 프로퍼티 접근

  List<MemberDto> result = queryFactory
            .select(Projections.bean(MemberDto.class,
                    member.username,
                    member.age))
            .from(member).fetch();

 

  2) 필드 접근

  List<MemberDto> result = queryFactory
            .select(Projections.fields(MemberDto.class,
                    member.username,
                    member.age))
            .from(member).fetch();
 

  3) 생성자 접근

  List<MemberDto> result = queryFactory
            .select(Projections.constructor(MemberDto.class,
                    member.username,
                    member.age))
            .from(member).fetch();

 

 

Note) 프로퍼티나 필드 접근 생성 방식에서 이름이 다를 때 해결 방안

  > ExpressionUtils.as(source,alias) : 필드나, 서브 쿼리에 별칭 적용

  > username.as("memberName") : 필드에 별칭 적용

예) queryFactory

                      .select(Projections.fields(UserDto.class

                             , member.username.as("name")

                             , ExpressionUtils.as( JPAExpressions.select(memberSub.age.max()).from(memberSub), "age") )                          ).from(member) .fetch();

 

3. @QueryProjection

  > @QueryProjection 어노테이션의 경우, QType을 생성하여 사용한다. 컴파일러로 타입을 체크할 수 있지만, DTO에 Querydsl 의존성과 DTO까지 Q파일을 생성해야 하는 단점이 있다.

 

1) MemberDto 수정

@QueryProjection

public MemberDto(String username, int age) {

    this.username = username;

    this.age = age;

}

 

2) ./gradlew compileQuerydsl > Q파일 생성

 

3) queryFactory.select(new QMemberDto(member.username, member.age))

                    .from(member) .fetch();

 

반응형