오봉이와 함께하는 개발 블로그

Querydsl - 프로젝션 결과 반환 (@QueryProjection) 본문

BE/JPA

Querydsl - 프로젝션 결과 반환 (@QueryProjection)

오봉봉이 2022. 9. 18. 22:45
728x90

프로젝션과 결과 반환 - @QueryProjection

생성자 + @QueryProjection

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

    public MemberDto() {
    }

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

@QueryProjection 추가 후 gradle -> other -> compileQuerydsl 후 QMemberDto 생성 확인

/**
 * study.querydsl.dto.QMemberDto is a Querydsl Projection type for MemberDto
 */
@Generated("com.querydsl.codegen.DefaultProjectionSerializer")
public class QMemberDto extends ConstructorExpression<MemberDto> {

    private static final long serialVersionUID = 1356709634L;

    public QMemberDto(com.querydsl.core.types.Expression<String> username, com.querydsl.core.types.Expression<Integer> age) {
        super(MemberDto.class, new Class<?>[]{String.class, int.class}, username, age);
    }

}
    @Test
    void findDtoByQueryProjection() {
        List<MemberDto> result = queryFactory
                .select(new QMemberDto(member.username, member.age))
                .from(member)
                .fetch();
        for (MemberDto memberDto : result) {
            System.out.println("memberDto = " + memberDto);
        }
    }
memberDto = MemberDto(username=member1, age=10)
memberDto = MemberDto(username=member2, age=20)
memberDto = MemberDto(username=member3, age=30)
memberDto = MemberDto(username=member4, age=40)

QMemberDto를 보면 생성자 메소드가 하나 생겼는데, 쿼리문을 작성할 때 생성자에 파라미터를 넣어서 실행하면 실행이 된다.

생성자(Constructor)와 비교하면 생성자는 아래와 같이 Dto에 만든 생성자와 맞지 않는 형식으로 코드를 작성해도 컴파일이 되기 때문에 런타임에서 오류가 발생한다.

.select(Projections.constructor(MemberDto.class,
        member.username,
        member.age,
        member.id))

하지만, 생성자 + @QueryProjection 방식을 통해서 작성하면 컴파일 할 때 오류를 잡을 수 있다는 장점이 있다.

다만, DTO에 Querydsl 어노테이션을 유지해야 하기 때문에 DB접근 기술을 바꾸게 되면 Querydsl에 대한 의존성이 생겼기 때문에 코드를 고쳐야 해서 DTO의 순수성을 유지할 수 없다는 단점과 DTO까지 Q파일을 생성해야 하는 단점이 있다.

아키텍쳐 설계 방향에 따라 어떤 방법을 사용할 것인지 정하면 된다.

distinct()

List<String> result = queryFactory
            .select(member.username).distinct()
            .from(member)
            .fetch();

distinct는 JPQL의 distinct와 같다.

인프런 김영한 지식공유자님 강의 : 실전! Querydsl
728x90
Comments