条件 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!

我不明白在定义最大结果后,结果集大小如何变小,因为行数小于定义的最大值。这肯定是一个错误,或者是否还有一些我不知道的冬眠的奇怪方面?


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


答案 1

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

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

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

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=?

请注意第一行 () 中的差异。类似的例子是 Java 类,它在 SQL 执行处理 SQL 行的结果。因此,当您指定 时,它将作为行限制应用于 SQL;SQL 在 中的元素上包含联接,因此您将 SQL 结果限制为 90 个子元素。一旦应用了转换器,这可能会导致少于20个根元素,这完全取决于在90个连接结果中哪些根元素碰巧首先出现。DISTINCTResultTransformerDISTINCT_ROOT_ENTITYmaxResultsCollectionDISTINCT_ROOT_ENTITY

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

从理论上讲,你应该考虑在SQL级别应用投影 - 类似的东西 - 但不幸的是不存在,我只是编造了它。也许应该!setProjectionc.setProjection(Projections.distinct(Projections.rootEntity()))Projections.rootEntity()


答案 2

setMaxResults 不适用于外部联接 SQL 查询。也许这是你的问题:Hibernate不会为为集合启用外部联接提取的查询返回不同的结果(即使我使用deliger关键字)?


推荐