ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • QuerydslRepositorySupport FetchResults Deprecated 대안
    JPA 2023. 11. 12. 00:01
    728x90

    개요

    QuerydslRepositorySupport를 활용하여 Paging을 구현하다가 FetchResults의 Deprecated를 발견하고 어떻게 대처했는지 기록하고자 합니다.

     

    • QuerydslRepositorySupport란 무엇인가?
    • QuerydslRepositorySupport에서 Paging을 처리하는 방법
    • FetchResults가 Deprecated 된 이유
    • 대안 및 해결방안

     

     

    QuerydslRepositorySuppprt란?

    public abstract class QuerydslRepositorySupport

    추상클래스로써 QueryDsl을 편하게 사용하기 위해 구현된 클래스입니다.

     

    QuerydslRepositorySupport에서 Paging을 처리하는 방법

    public <T> JPQLQuery<T> applyPagination(Pageable pageable, JPQLQuery<T> query) {
    
    	Assert.notNull(pageable, "Pageable must not be null");
    	Assert.notNull(query, "JPQLQuery must not be null");
    
    	if (pageable.isUnpaged()) {
    		return query;
    	}
    
    	query.offset(pageable.getOffset());
    	query.limit(pageable.getPageSize());
    
    	return applySorting(pageable.getSort(), query);
    }
    • getQuerydsl().applyPagination()을 통해 페이징을 queryDSL로 편리하게 변환 가능합니다.

     

    Pageable 객체와 JPQLQuery를 넘겨서 페이징 쿼리를 만들어냅니다.

    JPQLQuery는 인터페이스로 queryDSL 동적 쿼리 생성의 기준이 되는 인터페이스입니다.

    JpaQuery가 JPQLQuery 인터페이스를 구현하고 있습니다.

     

    offset, limit등을 적용하고 sort를 적용하여 JPQLQuery객체를 반환합니다.

     

    AbstractJPAQuery

    @Override
    @Deprecated
    public QueryResults<T> fetchResults() { ... }

    해당 클래스에서 fetchResults()를 구현하고 있습니다.

    하지만 @Deprecated 되어 있습니다.

     

    FetchResults가 Deprecated 된 이유는 무엇일까요?

    fetchResults를 이용하면 count 쿼리를 계산해서 반환합니다.

    하지만 간단한 쿼리에서만 동작하고 group by 절이 있는 쿼리나 having 절이 있는 쿼리는 메모리에서 카운트를 생성하게 되고 결과 집합이 큰 경우 심각한 성능 저하가 발생할 수 있습니다.

     

    count 쿼리가 별도로 필요하지 않은 경우에는 fetch()를 활용하는 것이 좋습니다.

     

    FetchRestuls 대안

    val content = querydsl!!.applyPagination(pageable, jpaQuery).fetch()
    
    val countQuery = jpaQueryFactory
    	.select(qOrder)
    	.from(qOrder)
    	.innerJoin(qOrderUser).on(qOrder.user.id.eq(qOrderUser.id))
    	.innerJoin(qOrderProductItem).on(qOrder.id.eq(qOrderProductItem.order.id))
    	.where(conditionQuery)
    
    
    return PageableExecutionUtils.getPage(content, pageable) { countQuery.fetch().count().toLong() }

    fetch()를 활용하고 count 쿼리는 직접 작성하여 반환합니다.

    Page를 위한 정보는 PageableExecutionUtils를 활용할 수 있습니다.

    PageableExecutionUtils 클래스는 첫번째 페이지나 마지막 페이지를 조회할 때 불필요한 count 쿼리를 조금 더 최적화해주는 역할을 수행합니다.

    댓글

Designed by Tistory.