簡體   English   中英

使用 JPA Criteria API 進行分頁的總行數

[英]Total row count for pagination using JPA Criteria API

我正在為我的系統中的實體實現“高級搜索”類型的功能,以便用戶可以使用該實體的屬性上的多個條件(eq、ne、gt、lt、like 等)來搜索該實體。 我使用 JPA 的 Criteria API 來動態生成 Criteria 查詢,然后使用setFirstResult() & setMaxResults()來支持分頁。 到目前為止一切都很好,但現在我想在結果網格上顯示結果總數,但我沒有看到獲得 Criteria 查詢總數的直接方法。
這是我的代碼的樣子:

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

我的結果集可能很大,所以我不想加載實體進行計數查詢,所以告訴我獲取總計數的有效方法,如 Criteria 上的rowCount()方法(我認為它在 Hibernate 的 Criteria 中)。

謝謝弗拉基米爾! 我接受了你的想法並使用了單獨的計數查詢來使用我現有的謂詞數組。 最終實現如下所示:

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

讓它工作。 任何的想法?

為什么不直接使用計數?

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

如果您使用 Hibernate 作為 JPA 提供者,請查看投影,尤其是Projections.rowCount()

不過,您可能需要執行兩次查詢,首先獲取計數,然后獲取結果。

請注意,對於普通 JPA,您可能需要其他一些方法。

我想這兩個答案都有效。 但它們都不是最佳的。 ThinkFloyd 的答案的問題是createQuery被使用了兩次。 Vladimir Ivanov創建了兩個CriteriaQuery實例,我認為這是不必要的。

val cb = entityManager.criteriaBuilder
val cq = cb.createQuery(ManualQuery::class.java)
val manualQuery = cq.from(ManualQuery::class.java)

val predicates = ArrayList<Predicate>()

/*
predications..... 
*/ 

cq.select(manualQuery)
        .where(*predicates.toTypedArray())
        .orderBy(cb.desc(manualQuery.get<ZonedDateTime>("createdDate")))

val query = entityManager.createQuery(cq)

// total rows count
val count = query.resultList.size

val indexedQuery = query
        .setFirstResult((currentPage - 1) * pageSize)
        .setMaxResults(itemsPerPage)

去做就行了。 它是在Kotlin 中完成的。 您在Java 中以相同的方式執行此操作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM