2011-03-18 3 views
22

사용자가 여러 조건 (eq, ne, gt, lt 등)을 사용하여 해당 엔티티를 검색 할 수 있도록 내 시스템의 엔티티에 대해 "고급 검색" 이 엔티티의 속성. JPA의 Criteria API를 사용하여 Criteria 쿼리를 동적으로 생성 한 다음 setFirstResult() & setMaxResults()을 사용하여 페이지 매김을 지원합니다. 이 시점까지는 모두 좋았지 만 지금은 결과 그리드에서 총 결과 수를 보여주고 싶지만 Criteria 쿼리의 총 수를 얻는 간단한 방법은 없습니다. 내 코드가 어떻게 보이는지
이입니다JPA를 사용하는 페이지 매김에 대한 총 행 개수 기준 API

CriteriaBuilder builder = em.getCriteriaBuilder(); 
CriteriaQuery<Brand> cQuery = builder.createQuery(Brand.class); 
Root<Brand> from = cQuery.from(Brand.class); 
CriteriaQuery<Brand> select = cQuery.select(from); 
. 
. 
//Created many predicates and added to **Predicate[] pArray** 
. 
. 
select.where(pArray); 
// Added orderBy clause 
TypedQuery typedQuery = em.createQuery(select); 
typedQuery.setFirstResult(startIndex); 
typedQuery.setMaxResults(pageSize); 
List resultList = typedQuery.getResultList(); 

내 결과 집합 그래서 나는 카운트 쿼리에 대한 나의 실체를로드하지 않으 큰 수, 등등 rowCount() 방법처럼 총 수를 얻기 위해 나에게 효율적인 방법을 말할 수 Criteria (나는 Hibernate의 Criteria에 있다고 생각한다).

답변

24

감사합니다. 블라디미르! 나는 당신의 생각을 따랐고 별도의 카운트 쿼리를 사용하여 기존의 필자 배열을 사용했습니다. 이 잘 작동하지만

CriteriaBuilder builder = em.getCriteriaBuilder(); 
CriteriaQuery<Brand> cQuery = builder.createQuery(Brand.class); 
Root<Brand> from = cQuery.from(Brand.class); 
CriteriaQuery<Brand> select = cQuery.select(from); 
. 
. 
//Created many predicates and added to **Predicate[] pArray** 
. 
. 
CriteriaQuery<Long> cq = builder.createQuery(Long.class); 
cq.select(builder.count(cq.from(Brand.class))); 
// Following line if commented causes [org.hibernate.hql.ast.QuerySyntaxException: Invalid path: 'generatedAlias1.enabled' [select count(generatedAlias0) from xxx.yyy.zzz.Brand as generatedAlias0 where (generatedAlias1.enabled=:param0) and (lower(generatedAlias1.description) like :param1)]] 
em.createQuery(cq); 
cq.where(pArray); 
Long count = em.createQuery(cq).getSingleResult(); 
. 
. 
select.where(pArray); 
. 
. 
// Added orderBy clause 
TypedQuery typedQuery = em.createQuery(select); 
typedQuery.setFirstResult(startIndex); 
typedQuery.setMaxResults(pageSize); 
List resultList = typedQuery.getResultList() 

을하지만

em.createQuery(cq); 

가이 작업을 진행하게 작성해야 할 이유를 아직도 잘 모르겠습니다 : 최종 구현은 다음과 같습니다. 어떤 아이디어?

+0

'em.createQuery (cq);를 정확히 추가해야하는 이유를 알 수 있었습니까? 고마워요 – Ittai

+0

이봐, 이건 내가 필요한 것 뿐이야. 왜이 줄이 필요한지 알고 싶다. –

+0

"Predicate"가이 부분의'Root from = cQuery.from (Brand.class); 부분에서'Root <>'를 사용하여 만들어지고 두 가지 모두에 사용된다는 사실과 관련이 있다고 생각합니다. 카운트 쿼리 및 페이징 된 쿼리 AFAIK 당신은'Root <>'객체를 사용하여 술어를 두 번 빌드해야합니다. 두 번째 것은이 줄에 숨겨져있다.'cq.select (builder.count (cq.from (Brand.class))); 왜 정확히'em.createQuery (cq);가 작동하는지 모르겠다. IMO는 예외를 throw해야한다. – Neilos

2

JPA-Provider로 최대 절전 모드를 사용하는 경우 projections, 특히 Projections.rowCount()을보십시오.

쿼리를 두 번 실행해야 할 수도 있습니다. 먼저 카운트를 가져 와서 결과를 얻으십시오.

일반 JPA의 경우 다른 접근 방법이 필요할 수 있습니다.

+3

-1. OP는 "JPA Criteria API"와 관련하여 ansers를 찾고 있다고 분명하게 명시했지만 답변이 다소 오도 된 것 같지 않습니까? (최대 절전 모드 투영을 암시하는 것은이 작업을 수행하는 방법입니다). 나는이 말을하고 있는데, 나는 그 질문에 비틀 거리면 나는 당신의 대답을 먼저 보았고 그 생각이 나를 혼란스럽게 만들었 기 때문에 (특히 당신과 유일하게 눈에 띄는 대답을 한 다음 대답 사이에 추가가 있었기 때문에). – Ittai

+0

@Ittai 잘, 그는 최대 절전 모드를 언급하고 이에 따라 질문을 표시했습니다 ... – Thomas

+0

당신이 질문을 읽을 때 그것이 최대 절전 모드가 아니라는 것을 알 것입니다. 그래서 많은 사람들이 사람들이 대답하는 것을 보았습니다. OP가 요구하는 것이 아니라 OP가 필요하다고 생각하십시오. 정직한 실수 인 것 같아서 질문을 수정하면 내 표가 바뀝니다. – Ittai

14

왜 카운트를 사용하지 않으시겠습니까?

CriteriaBuilder builder = em.getCriteriaBuilder(); 
CriteriaQuery<Long> cQuery = builder.createQuery(Long.class); 
Root<Brand> from = cQuery.from(Brand.class); 
CriteriaQuery<Long> select = cQuery.select(builder.count(from)); 
. 
. 
//Created many predicates and added to **Predicate[] pArray** 
. 
. 
select.where(pArray); 
// Added orderBy clause 
TypedQuery<Long> typedQuery = em.createQuery(select); 
typedQuery.setFirstResult(startIndex); 
//typedQuery.setMaxResults(pageSize); 
// here is the size of your query 
Long result = typedQuery.getSingleResult(); 
관련 문제