Database ( DB )/JPA, Querydsl

querydsl 5.0 - fetchResult, fetchCount deprecated

노루아부지 2022. 4. 17. 20:49

이전 프로젝트에서는 안 그랬는데 신규 프로젝트 개발을 위해 프로젝트를 생성했더니 아래 그림과 같이 fetchCount, fetchResults에 취소선이 생겨있어서 내용을 확인해봤습니다.

 

 

결론은 Querydsl 5.0부터 fetchResult()와 fetchCount()가 deprecated 되었습니다.

그에 대한 내용은 다음과 같습니다.

 

fetchResults() : Get the projection in QueryResults form. Make sure to use fetch() instead if you do not rely on the QueryResults.getOffset() or QueryResults.getLimit(), because it will be more performant. Also, count queries cannot be properly generated for all dialects. For example: in JPA count queries can’t be generated for queries that have multiple group by expressions or a having clause. Get the projection in QueryResults form. Use fetch() instead if you do not need the total count of rows in the query result.

 

fetchCount() : An implementation is allowed to fall back to fetch().size().

 

위 내용에 대해 요약하자면, 모든 dialect에서 QueryResults로 count 쿼리를 날리는 것이 완벽하게 지원되지 않기 때문에 total count를 사용할 필요가 없다면 fetch를 사용하라는 것입니다.

또한 fetchCount() 대신 fetch().size()를 사용하라는 말입니다.

 

 

 

1. fetchResults()

 

기존에 이렇게 코드를 작성했다면

@Override
public Page<MemberTeamDto> searchPageSimple(MemberSearchCondition condition, Pageable pageable) {
  QueryResults<MemberTeamDto> results = queryFactory
    .select(Projections.bean(MemberTeamDto.class,
      member.id,
      member.username,
      member.age,
      team.id,
      team.name
    ))
    .from(member)
    .offset(pageable.getOffset())
    .limit(pageable.getPageSize())
  .fetchResults();

  List<MemberTeamDto> content = results.getResults();
  long total = results.getTotal();

  return new PageImpl<>(content, pageable, total);
}

 

 

아래와 같이 바꿀 수 있습니다.

@Override
public Page<MemberTeamDto> searchPageSimple(MemberSearchCondition condition, Pageable pageable) {
  List<MemberTeamDto> content = queryFactory
    .select(Projections.bean(MemberTeamDto.class,
      member.id,
      member.username,
      member.age,
      team.id,
      team.name
    ))
    .from(member)
    .offset(pageable.getOffset())
    .limit(pageable.getPageSize())
  .fetch();

  return new PageImpl<>(content, pageable, content.size());
}

 

물론 위의 예시의 content.size()는 적절하지 않습니다. 적절하게 totalCount를 구해야 합니다.

 

[2023-08-30 추가]

어떤분이 content.size()가 왜 적절하지 않냐는 문의를 주셔서 추가합니다.

 

PageImpl의 선언부를 보면 다음과 같이 되어있습니다.

PageImpl 선언

'

즉, PageImpl의 세번째 인자값으로 들어가야 할 값은 현재 페이지의 갯수가 아닌 페이징처리를 하지 않았을 경우 조회가 되어야 하는 total count 입니다.

 

위 코드에서 content는 offset, limit를 사용하여 페이징 처리를 한 결과이기 때문에 content.size를 하면 total count가 아니라 현재 페이지의 count가 됩니다.

 

 

 

2. fetchCount()

기존에는 이렇게 fetchCount()를 통해 totalCount를 구했습니다.

@Override
public long getTotalCount(MemberSearchCondition condition, Pageable pageable) {
  return queryFactory
    .select(Projections.bean(MemberTeamDto.class,
      member.id,
      member.username,
      member.age,
      team.id,
      team.name
    ))
    .from(member)
  .fetchCount();
}

 

 

이후에는 아래와 같이 Wildcard.count를 통해 totalCount를 구할 수 있습니다.

@Override
public long getTotalCount(MemberSearchCondition condition, Pageable pageable) {
  return queryFactory
    .select(Wildcard.count)
    .from(member)
  .fetch().get(0);
}

 

728x90
loading