
1:1 번역이 아닙니다.
결과에서 count가 필요하지 않다면, 바로 fetch()로 치환하여 사용하세요. (근데 우리는 count가 필요해요!)
fetch()를 사용하세요! QueryResults.getOffset(), QueryResults.getLimit()에 의존적인 부분이 없다면 바로 변경해서 사용하세요. 대부분의 DB 플랫폼에선 성능이 훨씬 좋습니다.
일단, count() 쿼리 생성이 어려웠어요.
특히, 'multiple group by expression clauses', 'having clause'등이 사용된 쿼리문에서는 아예 불가능했죠.
불행하게도, JPQL(Query Launage, JPA)은 sub-query의 프로젝션을 허용하지 않아요. 그렇게 때문에 QueryDSL은 SELECT COUNT(*) FROM (<original query>)의 형식으로 sub-query를 랩핑하여 count()를 구해요.
결과론적으로, JPQL에서 count queries를 표현하기 위한 universal way(보편적인 방법)는 없어요.
여태까지 QueryDSL은 count()를 구하기 위해서 원본 쿼리를 수정하곤 했습니다. 그러나, 이 방법은 오직 간단한 쿼리에만 가능했어요. 특히, 'multiple group by clauses', 'having clause'에서는 불가능하거나 문제가 많이 발생했죠.
...
'multiple group by elements', 'having clause'가 포함된 쿼리를 지원하기 위해서, 우리는 메모리에 count를 저장했습니다. 결국은, fetch()의 결과를 반환하는 꼴이죠. Result sets의 크기가 상당하다면, 심각한 성능 저하를 일으킵니다.
'multiple group by elements' and/or 'a having claus'가 포함되는 복잡한 쿼리가 꼭 필요한 경우인가요? 그렇다면 차라리 QueryDSL과 Blaze-Persistence를 함께 사용하세요.
...
다시 한번 말하지만, Count()가 꼭 필요한 경우가 아니라면 fetch()로 치환하여 사용하세요.
해결하기 위해서는..
QueryDSL Team은 FetchResult()를 사용하지 않기를 권한다. (Group by, Having)등이 포함된 복잡한 쿼리는 Count 쿼리를 만들기 어렵기 때문이다. 정확히 말하자면, 원본 쿼리를 랩핑하는 형태로 구현하여 제공했었지만, 특정한 경우엔 급격한 성능 저하를 일으키기 때문이다.
ORM을 사용하다보면, Data를 온전히 Object 형태로 다루기 마련이다. 백엔드 개발자라면 실제 쿼리가 어떻게 실행되는지 놓치기 마련인데.. DSL문이 복잡한 형태를 띄우고 있다면, 한번쯤은 들여다보는 시간을 갖자!