JPA 2.0:任意 CriteriaQuery 的计数?
我正在尝试实现以下便捷方法:
/**
* Counts the number of results of a search.
* @param criteria The criteria for the query.
* @return The number of results of the query.
*/
public int findCountByCriteria(CriteriaQuery<?> criteria);
在 Hibernate 中,这是由
criteria.setProjection(Projections.rowCount());
什么相当于 JPA 中的上述内容?我发现了许多简单的计数示例,但它们都没有使用应确定行数的 CriteriaQuery。
编辑:
我不幸地发现@Pascal的答案不是正确的。这个问题非常微妙,只有在使用联接时才会出现:
// Same query, but readable:
// SELECT *
// FROM Brain b
// WHERE b.iq = 170
CriteriaQuery<Person> query = cb.createQuery(Person.class);
Root<Person> root = query.from(Person.class);
Join<Object, Object> brainJoin = root.join("brain");
Predicate iqPredicate = cb.equal(brainJoin.<Integer>get("iq"), 170);
query.select(root).where(iqPredicate);
当调用 findCountByCriteria(query)
时,它会因以下异常而终止:
org.hibernate.hql.ast.QuerySyntaxException: Invalid path: 'generatedAlias1.iq' [select count(generatedAlias0) from xxx.tests.person.dom.Person as generatedAlias0 where generatedAlias1.iq=170]
是否有其他方法可以提供这样的 CountByCriteria
代码>方法?
I am trying to implement the following convenience method:
/**
* Counts the number of results of a search.
* @param criteria The criteria for the query.
* @return The number of results of the query.
*/
public int findCountByCriteria(CriteriaQuery<?> criteria);
In Hibernate, this is done by
criteria.setProjection(Projections.rowCount());
What is the equivalent to the above in JPA? I found numerous simple count examples, but none of them made use of a CriteriaQuery whose row count should be determined.
EDIT:
I unfortunately found out that @Pascal's answer is not the correct one. The problem is very subtle and only shows up when you use joins:
// Same query, but readable:
// SELECT *
// FROM Brain b
// WHERE b.iq = 170
CriteriaQuery<Person> query = cb.createQuery(Person.class);
Root<Person> root = query.from(Person.class);
Join<Object, Object> brainJoin = root.join("brain");
Predicate iqPredicate = cb.equal(brainJoin.<Integer>get("iq"), 170);
query.select(root).where(iqPredicate);
When calling findCountByCriteria(query)
, it dies with the following exception:
org.hibernate.hql.ast.QuerySyntaxException: Invalid path: 'generatedAlias1.iq' [select count(generatedAlias0) from xxx.tests.person.dom.Person as generatedAlias0 where generatedAlias1.iq=170]
Is there any other way to provide such a CountByCriteria
method?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
我编写了一个实用程序类 JDAL JpaUtils 来执行此操作:
Long count = JpaUtils.count( em, criteriaQuery);
JpaUtils.copyCriteria(em, criteriaQueryFrom, criteriaQueryTo);
CriteriaQuery; countCriteria = JpaUtils.countCriteria(em, criteria)
等等...
如果您对源代码感兴趣,请参阅 JpaUtils.java
I wrote a utility class, JDAL JpaUtils to do it:
Long count = JpaUtils.count(em, criteriaQuery);
JpaUtils.copyCriteria(em, criteriaQueryFrom, criteriaQueryTo);
CriteriaQuery<Long> countCriteria = JpaUtils.countCriteria(em, criteria)
and so on...
If you are interested in the source code, see JpaUtils.java
我已经使用 cb.createQuery() (不带结果类型参数)对此进行了排序:
希望它有所帮助:)
我所做的类似于 CriteriaBuilder 的构建器,您可以在其中构建查询并调用 list() 或 count () 具有相同条件限制
I've sorted this out using the cb.createQuery() (without the result type parameter):
Hope it helps :)
What I did is something like a builder of a CriteriaBuilder where you can build a query and call list() or count() with the same criteria restrictions
上述解决方案都不适用于 EclipseLink 2.4.1,它们都以笛卡尔积 (N^2) 的计数结束,这是 EclipseLink 的一个小技巧,唯一的缺点是我不知道如果您正在从多个实体中选择,它将尝试从 CriteriaQuery 的第一个找到的根开始计数,但此解决方案不适用于 Hibernate(JDAL 可以,但 JDAL 不适用于 EclipseLink)
None of the above solutions work for EclipseLink 2.4.1, they all ended with a count on a Cartesian product (N^2), here is a small hack for EclipseLink, the only drawback is that I don't know what will happen if you are selecting FROM more than one Entity, it will try to count from the 1st found Root of your CriteriaQuery, this solution DOESN'T work for Hibernate though (JDAL does, but JDAL doesn't work for EclipseLink)
您在寻找这样的东西吗?
您可以这样使用:
PS:我不知道这是否是实现此目的的正确/最佳方法,仍在学习 Criteria API...
Are you looking for something like this?
That you could use like this:
PS: I don't know if this is the right/best way to implement this, still learning the Criteria API...
如果您想要结果和所有元素的计数,例如 Spring Data 的 Page - 您可以执行两个查询的元素。您可以做的是将条件与查询执行分开。
按城市查找用户的示例
除了 getUser 方法之外,您还可以构建第二个方法来对元素进行计数
,并且 createConditions 方法将处理这两个方法,因此您不必重复条件的逻辑。
在您的控制器中,您可以执行类似
long elementCount = yourCriteriaClassInstance.getElementCount(...); 的 操作
列出用户 = yourCriteriaClassInstance.getUsers(...)
if you want the result and the count of all elements like Spring Data's Page-Element you can do two queries. What you can do is to separate the criteria from the query-execution.
Example to find Users by City
addiional to the getUser Method you can build a second that will count your elements
and the createConditions Method will handle both, so you do not have to duplicate your logic for the criteria.
in your contoller you can do something like
long elementCount = yourCriteriaClassInstance.getElementCount(...);
List users = yourCriteriaClassInstance.getUsers(...)
标准查询的整体思想是它们是强类型的。因此,每个使用原始类型(在 CriteriaQuery 或 Root 或 Root 中没有泛型)的解决方案 - 这些解决方案都违背了该主要思想。我刚刚遇到了同样的问题,并且正在努力以“正确”(以及 JPA2)的方式解决它。
The whole idea of criteria queries is that they are strongly typed. So each solution, where you're using raw types (without generics in CriteriaQuery or Root or Root) - these solutions are against that main idea. I just run into the same issue and I'm struggling to solve it in a "proper" (along with JPA2) way.
我用 hibernate 和 criteria api
}
希望有帮助
i do somethig like thath with hibernate and criteria api
}
hope help