QueryDSL fetchResult, fetchCount의 deprecated와 사용 방법

hoyong.eom·2025년 3월 3일

JPA

목록 보기
6/8
post-thumbnail

JPA

QueryDSL을 사용하고 있어서 페이징 처리를 하려고 fetchResult를 보았더니 deprecated가 되었다?
구글링에 검색을 해보니 생각보다 오래전에 deprecated 되었더라..
회사에서는 queryDSL를 사용하고 있지 않으니 어쩔수 없나보다.

그럼 fetchResults가 무엇이고 deprecated되었으면 어떻게 사용해야하는지를 정리해보려고 한다.

fetchResults

queryDSL에서 쿼리 결과를 조회할 수 있는 함수는 여러 종류가 있다.
간단하게만 정리하면 아래와 같다.

  • fetch() : 리스트 조회, 데이터 없으면 빈 리스트 반환
  • fetchOne() : 단 건 조회
    결과가 없으면 null
    결과가 둘 이상이면 : com.querydsl.core.NonUniqueResultException
  • fetchFirst() : limit(1).fetchOne()과 같다.
  • [deprecated]fetchResults() : 페이징 정보를 포함, total count 쿼리가 추가로 실행된다.
  • [deprecated]fetchCount() : count 쿼리로 변경해서 count 수 조회
//List
 List<Member> fetch = queryFactory
 .selectFrom(member)
 .fetch();
 
 //단 건
Member findMember1 = queryFactory
 .selectFrom(member)
 .fetchOne();
 
 //처음 한 건 조회
Member findMember2 = queryFactory
 .selectFrom(member)
 .fetchFirst();
 
 //페이징에서 사용
QueryResults<Member> results = queryFactory
 .selectFrom(member)
.fetchResults();

 //count 쿼리로 변경
long count = queryFactory
 .selectFrom(member)
 .fetchCount();

즉, fetchResults는 페이징과 카운트 정보를 포함한 QueryResults라는 타입의 객체를 반환한다.

엄청 편리해보이는데 이게 왜 deprecated 된걸까?

deprecated가 된 이유

AbstractJPAQuery.java 코드에 들어가보면 deprecated된 이유가 서술되어있다.

그 이유가 위 설명에 잘나와있는데, 정리하면 다음과 같았다.

  • JPA에서 모든 dialects들에 대한 count 쿼리를 제대로 생성해주지 않는다.
  • JPA에서 여러개의 group by 표현식이나 , having 절이 있는 query에 대해 count query를 생성할 수 없다.

결론은 JPA에서 count 쿼리를 제대로 지원해주지 않으니 사용하지말라. 대신 fetch()를 사용해라!

참고
동일한 이유로 fetchCount() 도 deprecated되었다.

사용 방법

코드에서 설명되어 있던것처럼 fetchResults()를 사용하지 말고 fetch()를 사용해서 구현해야한다.

내 토이 프로젝트의 예시 구현은 아래와 같다.

   /**
     * bus_stop_name like %name% 쿼리 결과에 대한 Paging 쿼리
     * @param name
     * @param pageable
     * @return
     */
    @Override
    public Page<BusStop> searchBusStopPagingLikeName(String name, Pageable pageable) {

        List<BusStop> contents = queryFactory
                .selectFrom(busStop)
                .where(busStop.busStopName.contains(name))
                .offset(pageable.getOffset())
                .limit(pageable.getPageSize())
                .fetch();

        Long totalCount = queryFactory
                .select(busStop.count())
                .from(busStop)
                .where(busStop.busStopName.contains(name))
                .fetchOne();


        return new PageImpl<>(contents, pageable, totalCount);
    }

위 예시 코드를 보면 fetch()를 사용해서 페이징 쿼리 결과와 전체 count 쿼리를 나눠서 수행하였다.

0개의 댓글