QueryDsl과 Pageable을 이용한 Sort 기능 사용법
QueryDsl에서는 Client가 제공해준 Order를 사용하는 방법이 여러가지가 있다.
그 중 다음과 같은 코드를 사용하면 복잡한 분석기능을 사용하지않고, 클라이언트가 pageable에 제공하는 sort 정보를 모두 한 코드로 사용할 수 있다.
for (Sort.Order order : pageable.getSort()) {
PathBuilder<Object> path = new PathBuilder<Object>(Object.class, order.getProperty());
query.where(builder).orderBy(new OrderSpecifier(com.querydsl.core.types.Order.valueOf(order.getDirection().name()), path));
}
JPAQueryFactory에 where에 pageable.getSort()를 분석해서 추가해주는 코드이다.
Entity에 종속적이지 않고 공통으로 적용할 수 있다.
(존재하지 않는 컬럼등은 처리할 수 없음)
단점은 매번 페이징이 필요한 코드에 직접 추가해줘야 한다.
코드로 보면 이런 구조가 되기 쉽다.
// where, offset, limit 처리 완료 후
for (Sort.Order order : pageable.getSort()) {
PathBuilder<Object> path = new PathBuilder<Object>(Object.class, order.getProperty());
query.orderBy(new OrderSpecifier(com.querydsl.core.types.Order.valueOf(order.getDirection().name()), path));
}
var results = query.fetch();
return new PageImpl<>(results, pageable, count == null ? 0 : count);
for 루프 안에서 동작하기 때문에 따로 분리해줘서 호출해야해서 기능자체는 편리하지만 사용할때 귀찮다.
Utils로 분리해서 관리하기
첫번째 방법을 좀 더 쉽게 사용하려면 Utils로 분리하면 된다.
하지만 Utils로 분리하는 경우 QClass에 종속성이 생기게 된다.
하지만, 여러곳에서 사용하기 훨씬 편하고, 위 코드처럼 복잡하게 쿼리를 나눌 필요가 없어진다.
public abstract class QuerydslUtils {
public static <T> OrderSpecifier<?>[] getSort(Pageable pageable, EntityPathBase<T> qClass) {
return pageable.getSort().stream().map(order ->
new OrderSpecifier(
Order.valueOf(order.getDirection().name()),
Expressions.path(Object.class, qClass, order.getProperty())
)).toList()
.toArray(new OrderSpecifier[0]);
}
}
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.orderBy(QuerydslUtils.getSort(pageable, qProduct)).fetch();
return new PageImpl<>(results, pageable, count == null ? 0 : count);
기존처럼 offset, limit까지 끝난 query를 들고 orderBy를 설정 후 다시 fetch()를 호출하지 않고, 쿼리 내에서 자연스럽게 해결할 수 있다.
다만 어떤 QClass를 기준으로 정렬할것인지 정보가 필요하다.
위 코드는 qProduct 데이터에서 Client가 넘겨준 sort를 기준으로 정렬된다.
'JPA' 카테고리의 다른 글
[JPA] MySQL smallint Java Integer에 매핑하기 (0) | 2023.11.16 |
---|