QueryDsl의 Projections 활용
- Projections는 QueryDsl에서 제공하는 쿼리 결과의 dto 매핑을 위한 기능입니다.
- 불필요한 컬럼의 조회를 방지해 쿼리 조회시 발생하는 통신 비용을 줄일 수 있습니다.
- Projections에는 다음과 같은 네 가지 방법이 있습니다. 저희 조는 그 중에서도 @QueryProjection 을 활용해보았습니다.
- @QueryProjection
- Projections.bean(..)
- Projections.field(..)
- Projections.construct(..)
@QueryProjection
- Dto 생성자에 @QueryProjection 어노테이션을 붙여, Q-Type 클래스를 만들어 사용하는 방법입니다.
- 컴파일 시점에 에러를 잡아낼 수 있어 안전하다는 장점이 있습니다.
- 해당 장점을 고려하여, 저희 팀은 @QueryProjection을 활용해보았습니다.
- 그러나 Dto도 Q-Type을 생성한다는 점과 Dto가 QueryDSL에 대한 의존성을 갖게 된다는 단점이 존재합니다.
- 컴파일 시점에 에러를 잡아낼 수 있어 안전하다는 장점이 있습니다.
@Override
public Page<ReviewResponseDto> searchReviewByUser(UUID userId, Pageable pageable) {
List<ReviewResponseDto> dtoList = queryFactory
.select(new QReviewResponseDto(review.reviewId,
new QReviewUserResponseDto(user.userId, user.username, user.nickname),
new QReviewRestaurantResponseDto(restaurant.resId, restaurant.resName),
review.reviewScore, review.reviewContent, review.reviewImageUrl, review.order.orderId, review.isPublic,
review.createdAt)
)
.from(review)
.leftJoin(user).on(user.userId.eq(review.user.userId))
.leftJoin(restaurant).on(restaurant.resId.eq(review.restaurant.resId))
.where(
eqUserId(userId),
review.deletedAt.isNull()
)
.orderBy(createOrderSpecifiers(pageable.getSort()))
.offset(pageable.getOffset())
.limit(validatePageSize(pageable.getPageSize()))
.fetch();
//... 생략
return PageableExecutionUtils.getPage(dtoList, pageable, () -> countQuery.fetchOne());
}
Projections.bean(..)
- Setter와 기본 생성자가 필요합니다.
- Dto 객체는 불변 객체로 사용하는 것을 지향하기 때문에 Setter 를 사용한다는 점에서 아쉬운 부분이 있습니다.
List<MemberDto> result = queryFactory
.select(Projections.bean(MemberDto.class,
member.username,
member.age))
.from(member)
.fetch();
Projections.field(..)
- 기본 생성자가 필요하며, Dto의 필드명과 Projection의 컬럼명이 일치하면 값 매핑이 동작합니다.
- 만약 필드명과 컬럼명이 다를 경우에는 별칭(alias)을 사용하여 매핑할 수 있습니다.
List<MemberDto> result = queryFactory
.select(Projections.fields(MemberDto.class,
member.username.as("name"),
member.age))
.from(member)
.fetch();
Projections.construct(..)
- 매핑할 필드를 매개변수로 받는 생성자가 필요합니다. 생성자를 사용하여 필드에 매핑시켜 주는 방법입니다.
List<MemberDto> result = queryFactory
.select(Projections.constructor(MemberDto.class,
member.username,
member.age))
.from(member)
.fetch()
}
참고 페이지
'Spring' 카테고리의 다른 글
스프링 AOP를 이용한 권한체크 작업해보기 (0) | 2025.03.19 |
---|---|
스프링 로깅 Spring Logging (0) | 2025.02.24 |
[Jpa/QueryDsl] QueryDsl 설정 및 조회 기능 구현 (+동적 정렬) (0) | 2025.02.16 |
[Springboot]@WebMvcTest 사용 중 security csrf 오류 해결 (2) | 2023.11.26 |
Spring Security 기본 (0) | 2023.10.05 |