java - Criteria API 返回的结果集太小

标签 java hibernate criteria hibernate-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);
<b>criteria.setMaxResults(90);</b>
criteria.add(Restrictions.eq("active",true));
List list = criteria.list();

.. 现在列表的大小是 18!

我不明白在定义最大结果后结果集的大小如何变小,因为行数小于定义的最大值。这看起来确实像是一个错误,或者是否又出现了一些我不知道的 hibernate 的奇怪方面?


如果您正在寻找此问题的答案,请务必阅读已接受的答案及其评论。

最佳答案

通过在 Hibernate 中打开 SQL 调试并比较生成的查询,可以非常清楚地看到这里发生了什么。

使用相当简单的 SaleItem 一对多映射(希望是不言自明的),基于 Criteria像这样查询:

Criteria c = sessionFactory.getCurrentSession().createCriteria(Sale.class);
c.createAlias("items", "i");
c.add(Restrictions.eq("i.name", "doll"));
c.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
c.setMaxResults(2);

产生这样的SQL:

select top ? this_.saleId as saleId1_1_, ... 
from Sale this_ 
inner join Sale_Item items3_ on this_.saleId=items3_.Sale_saleId 
inner join Item items1_ on items3_.items_id=items1_.id 
where items1_.name=?

而像这样的查询:

Query q = sessionFactory.getCurrentSession().createQuery("select distinct s from Sale s join s.items as i where i.name=:name");
q.setParameter("name", "doll");
q.setMaxResults(2);

产生类似的东西:

select top ? distinct hibernated0_.saleId as saleId1_ 
from Sale hibernated0_ 
inner join Sale_Item items1_ on hibernated0_.saleId=items1_.Sale_saleId 
inner join Item hibernated2_ on items1_.items_id=hibernated2_.id 
where hibernated2_.name=?

请注意第一行的区别 (DISTINCT)。像 DISTINCT_ROOT_ENTITY 这样的 ResultTransformer 是一个 Java 类,它在 SQL 执行后 处理 SQL 行的结果。因此,当您指定 maxResults 时,它将作为行限制应用于 SQL; SQL 包含对 Collection 中元素的连接,因此您将 SQL 结果限制为 90 个子元素。一旦应用了 DISTINCT_ROOT_ENTITY 转换器,可能会导致少于 20 个根元素,这完全取决于哪些根元素恰好在 90 个连接结果中最先出现。

DISTINCT 在 HQL 中的行为非常不同,因为它实际上使用了 SQL DISTINCT 关键字,该关键字在 行限制之前应用。因此,它的行为符合您的预期,并解释了两者之间的区别。

理论上,您应该查看 setProjection 以在 SQL 级别应用投影——类似于 c.setProjection(Projections.distinct(Projections.rootEntity())) -- 但不幸的是 Projections.rootEntity() 不存在,我只是编造的。也许应该!

关于java - Criteria API 返回的结果集太小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2183617/

相关文章:

java - 使用 Hibernate 提交事务时出现 ConcurrentModificationException

c# - NHibernate.查询异常 : duplicate association path

grails - Grails条件查询检查 `OR`逻辑

java - 理解Java继承过程中的泛型转发

java - 为什么我的文字没有出现在微调器的 ImageView 中?

java - 如何从 JPA 中的父实体记录中删除子实体?

java - JPA + Hibernate 出现 NoSuchFieldError

java - 没有 createQuery() 的 Hibernate 连接

java - 每月更新一条数据库记录

java - 将动态内容压缩到 ServletOutputStream