这怎么可能,我必须遵循标准
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!
我不明白定义最大结果后结果集的大小如何减小,因为行数小于定义的最大数。这肯定看起来像是个错误,还是再次出现了我不知道的一些奇怪的hibernate状态?
如果您正在寻找该问题的答案,请确保阅读已接受的答案及其评论。
通过在Hibernate中打开SQL调试并比较生成的查询,可以很清楚地看到此处发生的情况。
使用一个相当简单的Sale→ Item一对多映射(希望是不言自明的),这样的Criteria基于-的查询如下:
Sale
Item
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这样的:
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=?
请注意第一行中的区别(DISTINCT)。甲ResultTransformer像DISTINCT_ROOT_ENTITY是一个Java类,该处理SQL行的结果 之后 被执行的SQL。因此,当您指定时maxResults,它将被用作SQL的行限制;SQL包含对中元素的联接Collection,因此您将SQL结果限制为90 个子元素 。一旦应用了DISTINCT_ROOT_ENTITY转换器,可能会导致少于20个根元素,这完全取决于在90个连接结果中哪个根元素碰巧排在最前面。
DISTINCT
ResultTransformer
DISTINCT_ROOT_ENTITY
maxResults
Collection
DISTINCTHQL中的行为实际上有很大不同,因为它实际上使用了SQL DISTINCT关键字,该关键字在行限制 之前 应用。因此,它的行为符合您的预期,并解释了两者之间的区别。
从理论上讲,您应该考虑在setProjectionSQL级别上应用投影- 之类的东西c.setProjection(Projections.distinct(Projections.rootEntity()))-但不幸的Projections.rootEntity()是不存在,我只是编造了。也许应该!
setProjection
c.setProjection(Projections.distinct(Projections.rootEntity()))
Projections.rootEntity()