2011-03-18 15 views
22

Sistemimdeki bir Varlık için "Gelişmiş Arama" işlev türünü uygularım, böylece kullanıcının bu koşulu birden çok koşul (örneğin, eq, ne, gt, lt, vb.) Kullanarak arayabilir Bu varlığın nitelikleri hakkında. Dinamik olarak Kriteri sorgusunu oluşturmak için JPA'nın Kriterler API'sini kullanıyorum ve sayfa numaralandırmayı desteklemek için setFirstResult() & setMaxResults()'u kullanıyorum. Bu noktaya kadar her şey yolundaydı, ancak şimdi sonuçların grid sonuçlarında toplam sayısını göstermek istiyorum ancak Kriterler sorgusunun toplam sayısını elde etmek için ileriye doğru bir yol görmedim. Benim kod nasıl göründüğünü
budur:JPA Ölçütleri API'sini kullanarak sayfalandırma için toplam satır sayısı

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(); 

Benim sonuç kümesi yüzden sayım sorgusu için benim varlıkları yüklemek istemiyorum büyük olması, böylece rowCount() yöntemle gibi toplam sayısını almak için bana etkili yolu söyleyebilirdi Kriterler (Ben orada Hibernate Kriterleri'nde olduğunu düşünüyorum).

cevap

24

Teşekkürler Vladimir! Fikrinizi aldım ve içinde varolan yüklemler dizilimini kullanmak için ayrı sayım sorgusu kullandım. Bu iyi çalışıyor olsa

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() 

ama

em.createQuery(cq); 

almak o çalışma yazmak zorunda neden hala emin değilim: Nihai uygulama aşağıdaki gibi görünüyor. Herhangi bir fikir?

+0

Niçin 'em.createQuery (cq);' yi eklemeniz gerektiğini tam olarak öğrenebildiniz mi? Teşekkürler – Ittai

+0

Hey, bu sadece ihtiyacım olan şey ... bu da neden bu hat gerekli olduğunu bilmek isterim! –

+0

"Predicate" in bu bölümden "Root <>" kullanılarak oluşturulduğundan şüpheleniyorum. "Root = cQuery.from (Brand.class);' ve sonra ikisi için kullanılır sayma sorgusu ve disk belleği sorgusu. AFAIK, hem 'Root <> 'nesnelerini kullanarak iki kez yüklemleri oluşturmanız gerekir. İkincisi bu satırda gizlidir. Cq.select (builder.count (cq.from (Brand.class))); '. Neden tam olarak em.createQuery (cq); 'bilmiyorum çalışır, IMO bir istisna atmalıdır. – Neilos

2

JPA Sağlayıcınız olarak Hazırda Bekletme özelliğini kullanıyorsanız, projections, özellikle Projections.rowCount().

Sorguyu iki kez olsa çalıştırmanız gerekebilir, önce sayımı yapın ve sonuçları alın.

Sade JPA için başka bir yaklaşıma ihtiyacınız olabileceğini unutmayın.

+3

-1. OP, "JPA Kriteri API'sı" ile ilgili olarak ansörleri aradığını açıkça belirtti, cevabın biraz yanıltıcı olduğunu düşünmüyor musunuz? (Hazırda bekletme projeksiyonlarını ima etmenin yolu budur). Bunu söylüyorum çünkü soruya cevap verdiğimde ilk önce cevabını gördüm ve bu şekilde düşünmem için kafamı karıştırdı. (Özellikle de sizin aranızdaki tek cevabın yanında görünen tek cevap olduğu için bir ekleme olduğu için). – Ittai

+0

@Ittai, Hibernate'den bahsetmiş ve buna göre soruyu işaretlemişti ... – Thomas

+0

Soruyu okuduktan sonra, hazırda beklemediğini görüyorsanız, sanırım çok fazla insan var. OP'nin istediğini değil OP'nin istediğini düşünün. Dürüst bir hata gibi göründüğünden, sorunuzu düzenlerseniz oylarımı değiştiririm. – Ittai

14

Neden sayımı kullanmıyorsunuz?

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(); 
İlgili konular