这怎么可能,我必须遵循标准
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!
我不明白定义最大结果后结果集大小如何变小,因为行数小于定义的最大值。这肯定好像是一个bug,或者是否还有一些我不知道的hibernate奇怪的方面?
如果您正在寻找此问题的答案,请务必阅读已接受的答案及其评论。
答案 0 :(得分:9)
通过在Hibernate中打开SQL调试并比较生成的查询,可以非常清楚地看到这里发生的事情。
使用相当简单的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 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
行为非常不同,因为它实际上使用了SQL DISTINCT
关键字,该关键字在行限制之前应用。因此,这表现得如您所愿,并解释了2之间的区别。
理论上你应该看setProjection
在SQL级别应用一个投影 - 类似于c.setProjection(Projections.distinct(Projections.rootEntity()))
- 但不幸的是Projections.rootEntity()
不存在,我只是做了它起来。也许它应该!
答案 1 :(得分:2)
setMaxResults不适用于外连接SQL查询。也许这是你的问题:Hibernate does not return distinct results for a query with outer join fetching enabled for a collection (even if I use the distinct keyword)?。
答案 2 :(得分:1)
另一种解决方案如下:
criteria.list()
而不设置任何别名=>将使用proxies =>填充根实体的引用集/列表。在这里你正确设置了最大结果等这样的事情:
Criteria criteria = this.getSession().createCriteria(User.class);
criteria.setResultTransformer(CriteriaSpecification.ROOT_ENTITY);
criteria.setMaxResults(10);
// First get the results without joining with the other tables
List<User> results = criteria.list();
// at this point the set roles is filled with proxies
// we'll now create and execute the join so these proxies are filled since we're still in the same session
getSession().createCriteria(User.class, "u")
.createAlias("u.roles", "r", CriteriaSpecification.LEFT_JOIN)
.list();
return results;
希望这可以提供帮助,
斯泰恩
答案 3 :(得分:1)
希望这可以提供帮助
public List<Employee> getData(int to, int from) {
Criteria hCriteria = null;
List<Employee> viewDataList = null;
List<Employee> exactDataList = null;
try {
hSession = HibernateSessionFactory.getSession();
hTransaction = hSession.beginTransaction();
hCriteria = hSession.createCriteria(Employee.class);
/*
hCriteria.setFirstResult(to);
hCriteria.setFirstResult(from);
*/
hCriteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
viewDataList = hCriteria.list();
// for limit
exactDataList=viewDataList.subList(from,to);
hTransaction.commit();
} catch (Exception e) {
hTransaction.rollback();
} finally {
try {
hSession.flush();
HibernateSessionFactory.closeSession();
} catch (Exception hExp) {
}
}
return exactDataList;
}
答案 4 :(得分:0)
这是hibernate中的一个已知问题。查看@Cowan以获取生成的SQL以及问题的解释。在他们的jira中有一个开放的错误请求。让我们希望有人出现并修复它:)