使用JPA Criteria API进行分页的总行数

Thi*_*oyd 26 java pagination hibernate jpa kotlin

我正在为我的系统中的实体实现"高级搜索"类功能,以便用户可以使用此实体的属性上的多个条件(eq,ne,gt,lt等)搜索该实体.我正在使用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();
Run Code Online (Sandbox Code Playgroud)

我的结果集可能很大,所以我不想加载我的实体进行计数查询,所以告诉我有效的方法来获得像rowCount()Criteria上的方法一样的总计数(我认为它在Hibernate的Criteria中).

Thi*_*oyd 30

谢谢弗拉基米尔!我接受了你的想法,并使用单独的计数查询来使用我现有的谓词数组.最终实现如下:

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()
Run Code Online (Sandbox Code Playgroud)

虽然这工作正常,但我仍然不确定为什么我要写

em.createQuery(cq);
Run Code Online (Sandbox Code Playgroud)

让它工作.任何的想法?


Vla*_*nov 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();
Run Code Online (Sandbox Code Playgroud)