Criteria API 返回的结果集太小
这怎么可能,我必须遵循标准
Criteria criteria = getSession().createCriteria(c);
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
criteria.add(Restrictions.eq("active",true));
List list = criteria.list();
列表的大小现在是 20。如果我向标准添加最大结果,
Criteria criteria = getSession().createCriteria(c);
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
criteria.setMaxResults(90);
criteria.add(Restrictions.eq("active",true));
List list = criteria.list();
..现在列表的大小是 18!
我不明白定义最大结果后结果集大小如何变小,因为行数小于定义的最大值。这确实看起来像一个错误,或者休眠中是否又存在一些我不知道的奇怪方面?
如果您正在寻找此问题的答案,请务必阅读已接受的答案及其评论。
How is this possible, I have to following criteria
Criteria criteria = getSession().createCriteria(c);
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
criteria.add(Restrictions.eq("active",true));
List list = criteria.list();
The size of list is now 20. If I add a max results to the criteria,
Criteria criteria = getSession().createCriteria(c);
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
criteria.setMaxResults(90);
criteria.add(Restrictions.eq("active",true));
List list = criteria.list();
.. now list's size is 18!
I don't understand how the resultsets size can be smaller after defining the max results, as the amount of rows is smaller than the defined max. This sure seems like a bug, or is there again some weird aspects of hibernate that I'm not aware of?
If you're looking for an answer to this question, make sure to read the accepted answer and its comments.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
setMaxResults 不适用于外连接 SQL 查询。也许这是你的问题: Hibernate 不会为启用了外连接获取的查询返回不同的结果集合(即使我使用 unique 关键字)?。
The setMaxResults does not work with outer join SQL queries. Maybe this is your problem: Hibernate does not return distinct results for a query with outer join fetching enabled for a collection (even if I use the distinct keyword)?.
希望这可以有所帮助
Hope this can be help
另一个解决方案如下:
criteria.list()
而不设置任何别名 =>根实体的引用集/列表将填充代理 =>在这里,您正确设置了最大结果,并如下所示:
希望这可以有所帮助,
斯泰因
Another solution is the following:
criteria.list()
without setting any alias => the referenced sets/list of the root entity will be filled with proxies => here you set correctly the max results and suchSomething like this:
Hope this can help,
Stijn
这是休眠中的一个已知问题。查看@Cowan 生成的 SQL 和问题的解释。他们的 jira 中有一个针对此问题的开放错误请求。希望有人能解决这个问题:)
https://hibernate.atlassian.net/browse/ HB-520
This is a known problem in hibernate. Look at @Cowan for a generated SQL and an explanation of the problem. There is an open bug request for this in their jira. Let's hope that someone comes along and fixes it :)
https://hibernate.atlassian.net/browse/HB-520
通过在 Hibernate 中打开 SQL 调试并比较生成的查询,可以非常清楚地看到这里发生的情况。
使用相当简单的
Sale
→Item
一对多映射(希望是不言自明的),基于Criteria
的查询如下:生成这样的 SQL:
而像这样的
Query
则生成如下内容:
注意第一行中的差异 (
DISTINCT
)。类似DISTINCT_ROOT_ENTITY
的ResultTransformer
是一个 Java 类,它在执行 SQL 后处理 SQL 行的结果。因此,当您指定maxResults
时,它将用作 SQL 的行限制; SQL 包含对Collection
中元素的联接,因此您将 SQL 结果限制为 90 个子元素。应用 DISTINCT_ROOT_ENTITY 转换器后,可能会导致根元素少于 20 个,这完全取决于 90 个连接结果中哪个根元素恰好首先出现。HQL 中的
DISTINCT
的行为非常不同,因为它实际上使用 SQLDISTINCT
关键字,该关键字在行限制之前应用。因此,这会按照您的预期运行,并解释了两者之间的差异。理论上,您应该查看
setProjection
以在 SQL 级别应用投影 - 类似c.setProjection( Projections.distinct(Projections.rootEntity()))
- 但不幸的是Projections.rootEntity()
不存在,我只是编造了它。或许应该如此!What is happening here can be seen very clearly by turning on SQL debugging in Hibernate and comparing the generated queries.
Using a fairly simple
Sale
→Item
one-to-many mapping (which is hopefully self-explanatory), aCriteria
-based query like this:produces SQL like this:
whereas a
Query
like this:produces something like:
Note the difference in the very first line (
DISTINCT
). AResultTransformer
likeDISTINCT_ROOT_ENTITY
is a Java class, which processes the results of the SQL rows after the SQL is executed. Therefore, when you specify amaxResults
, that will be applied as a row limit on the SQL; the SQL includes a join onto the elements in theCollection
, so you're limiting your SQL result to 90 sub-elements. Once theDISTINCT_ROOT_ENTITY
transformer is applied, that may result in less than 20 root elements, purely dependent on which root elements happen to come out first in the 90 joined results.DISTINCT
in HQL behaves very differently, in that that actually uses the SQLDISTINCT
keyword, which is applied before the row limit. Therefore, this behaves as you expect, and explains the difference between the 2.In theory you should be looking at
setProjection
to apply a projection at the SQL level -- something likec.setProjection(Projections.distinct(Projections.rootEntity()))
-- but unfortunatelyProjections.rootEntity()
doesn't exist, I just made it up. Perhaps it should!