繁体   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