Querydsl) groupBy + fetchCount() 오류 발생

yejin25·2021년 9월 29일
0
nested exception is java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: expecting CLOSE, found ',' near line 1, column 46 [select count(distinct Activity.id, Activity.activityDate) 
org.hibernate.hql.internal.ast.QuerySyntaxException: expecting CLOSE, found ',' near line 1, column 46 [select count(distinct Activity.id, Activity.activityDate)

왜 이러세요... 😭

📌 오류 발생

@Override
  public Page<yearActivityListDTO> findMonthListWithActivity(Pageable pageable){
    BooleanBuilder builder = new BooleanBuilder();
    builder.and(Activity.activityDate.between(current.minusYears(1), current));
    current.toLocalDate();

    final JPQLQuery<yearActivityListDTO> query = from(Activity)
        .where(builder)
        .select(new QyearActivityListDTO(Activity.activityDate, Activity.farm.id, Activity.value.sum()));

    List<yearActivityListDTO> result = getQuerydsl().applyPagination(pageable, query).fetch();

        return new PageImpl<>(result, pageable, query.fetchCount());
  }

이 코드는 잘 실행된다. 여기서 groupBy 조건이 필요해서 추가했더니

다음과 같은 오류가 발생했다. 처음엔 groupBy 가 2개 이상의 인자는 받지 않는다고 생각하고
'groupBy multiple' 과 같이 검색해가며 찾아보았더니 groupBy(x, y)는 맞게 쓴거였다. 디버깅해보니 쿼리문은 정상적으로 데이터를 가져오고 있었다.

오류 메세지에서는 사실 groupBy 라인이 아니라 아래쪽에 페이징을 위한 return 라인을 가리키고 있었다. IDE 오류 메세지 믿을걸 groupBy(x)로 바꾸면 잘 되길래 groupBy 문제인줄



📌 원인 발견

혹시나 해서 Querydsl repository issue 에 방문해 보았더니...

이미 논의 중이던 문제였고 아직까지도 해결되지 못한 문제로 남아있는 것 같다.
근데 이슈는 닫혀있음 뭐지?

정리해보면, groupBy(x, y)fetchResults(), fetchCount()를 같이 사용하면 오류가 발생한다.

👉 https://github.com/querydsl/querydsl/issues/2504
👉 https://github.com/querydsl/querydsl/pull/2605

위 링크로 가보면 같은 문제로 고통을 호소하는 개발자들을 볼 수 있다..

깃허브를 확인한 후 오류 메세지를 구글링 해봤는데 나랑 같은 문제를 겪는 사람들의 글을 볼 수 있었다. groupBy에 꽂혀서 오류 메세지 검색할 생각을 못했다. 아니었으면 삽질을 덜 했을텐데...



📌 해결해보려 했으나 결국

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

위와 같이 쿼리의 개수를 셀 수 있게 쿼리의 결과 리스트의 사이즈를 넣어주면 된다고 생각했다.

실행해보니 오류는 없었지만 데이터가 pagination size를 5라고 했다고 하면 딱 5개만 출력되었다. 덕분에 쿼리의 결과가 리스트에 한번에 저장되는게 아니라는 사실을 알게 되었다. (정상적으로 출력되면 33페이지까지 존재해야한다)

다른 사람들의 해결방식을 보니 코드를 아예 다시 써야하는 수준이었다. JPA -> Mybatis로 옮길 생각을 하는 사람도 보았다. 일단 pagination은 혹시 필요할까봐 작성한 것이었기 때문에 포기한 채 원하는 데이터만 잘 가져오도록 하기로 했다.

  @Override
  public List<yearActivityListDTO> findMonthListWithActivity() {
    BooleanBuilder builder = new BooleanBuilder();

    builder.and(Activity.activityDate
        .between(
            LocalDateTime.now().minusYears(1),
            LocalDateTime.now()
        ));

    return from(Activity)
        .where(builder)
        .select(new QyearActivityListDTO(Activity.activityDate.yearMonth(), Activity.farm.id ,Activity.value.sum()
            ))
        .groupBy(Activity.farm, Activity.activityDate.yearMonth())
        .fetch();
  }


찝찝하지만.. 끝😕

page 기능이 필요해지면 다른 방식으로 pagination 할 수 있는 방법을 찾아보고 적용시킬 예정이다. pagination하는 방법은 다양했던 걸로 기억하기 때문에 fetchCount()를 쓰지 않아도 될지도..

0개의 댓글