15

这怎么可能,我必须遵循标准

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!

我不明白定义最大结果后结果集大小如何变小,因为行数小于定义的最大值。这肯定看起来像一个错误,还是我不知道休眠的一些奇怪方面?


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

4

5 回答 5

9

通过在 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像这样:

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) 的区别。ResultTransformerlike是一个Java 类,它在 SQL 执行DISTINCT_ROOT_ENTITY处理 SQL 行的结果。因此,当您指定 a时,它将作为 SQL 的行限制应用;SQL 包括对 中元素的连接,因此您将 SQL 结果限制为 90个子元素。一旦应用了转换器,这可能会导致少于 20 个根元素,这完全取决于在 90 个连接结果中哪些根元素碰巧首先出现。maxResultsCollectionDISTINCT_ROOT_ENTITY

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

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

于 2010-02-02T23:14:50.987 回答
2

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

于 2010-02-02T11:57:52.713 回答
1

另一种解决方案如下:

  1. 在不设置任何别名的情况下运行您的criteria.list()=>根实体的引用集/列表将充满代理=>在这里您正确设置了最大结果等
  2. 在同一个休眠会话中自行运行别名条件 => 将初始化上述代理

像这样的东西:

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;

希望这可以帮助,
Stijn

于 2010-11-29T16:22:25.520 回答
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;
}
于 2012-07-04T07:10:15.083 回答
0

这是休眠中的一个已知问题。查看@Cowan 以获取生成的 SQL 和问题的解释。在他们的 jira 中有一个开放的错误请求。让我们希望有人来解决它:)

https://hibernate.atlassian.net/browse/HB-520

于 2013-11-06T16:28:33.707 回答