Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Criteria API返回的结果集太小_Java_Hibernate_Criteria_Hibernate Criteria - Fatal编程技术网

Java Criteria API返回的结果集太小

Java Criteria API返回的结果集太小,java,hibernate,criteria,hibernate-criteria,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(); 列表的大小现在是20。如果我在标准中添加一个max results Criteria cr

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

Criteria criteria = getSession().createCriteria(c);
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
criteria.add(Restrictions.eq("active",true));
List list = criteria.list();
列表的大小现在是20。如果我在标准中添加一个max results

Criteria criteria = getSession().createCriteria(c);
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
criteria.setMaxResults(90);
criteria.add(Restrictions.eq("active",true));
List list = criteria.list();
Criteria=getSession().createCriteria(c);
criteria.setResultTransformer(criteria.DISTINCT\u ROOT\u实体);
标准:setMaxResults(90);
标准。添加(限制。等式(“活动”,真实));
List=criteria.List()
。。现在列表的大小是18

我不明白在定义了max results之后,resultset的大小怎么会变小,因为行的数量小于定义的max。这看起来确实像是一个bug,或者hibernate还有一些我不知道的奇怪方面吗



如果您正在寻找此问题的答案,请确保阅读接受的答案及其注释。

setMaxResults不适用于外部联接SQL查询。这可能是您的问题:。

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

使用相当简单的
销售
→ <代码>项
一对多映射(希望是自解释的),一个基于
条件的查询,如下所示:

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);
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);
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;
生成如下SQL:

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);
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);
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;
而像这样的
查询

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);
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);
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;
产生类似于:

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
like
DISTINCT\u ROOT\u ENTITY
是一个Java类,它在执行SQL后处理SQL行的结果。因此,当您指定一个
maxResults
时,它将作为SQL上的行限制应用;SQL包含到
集合
中元素的联接,因此您将SQL结果限制为90个子元素。一旦应用了
DISTINCT_ROOT_ENTITY
transformer,可能会导致少于20个根元素,这完全取决于哪个根元素恰好在90个连接的结果中最先出现

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


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

另一种解决方案如下:

  • 运行
    criteria.list()
    而不设置任何别名=>根实体的引用集/列表将填充代理=>在这里您可以正确设置最大结果等
  • 在同一hibernate会话中单独运行别名条件=>上述代理将被初始化
  • 大概是这样的:

    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);
    
    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);
    
    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;
    
    Criteria=this.getSession().createCriteria(User.class);
    标准.setResultTransformer(标准规范.根实体);
    标准:setMaxResults(10);
    //首先,在不与其他表联接的情况下获取结果
    列表结果=标准。列表();
    //此时,集合角色中充满了代理
    //现在,我们将创建并执行连接,以便填充这些代理,因为我们仍处于同一会话中
    getSession().createCriteria(User.class,“u”)
    .createAlias(“u.roles”,“r”,CriteriaSpecification.LEFT_JOIN)
    .list();
    返回结果;
    
    希望这能有所帮助,
    Stijn

    希望这能有所帮助

    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;
    }
    
    public List getData(int-to,int-from){
    标准hCriteria=null;
    List viewDataList=null;
    List exactDataList=null;
    试一试{
    hSession=HibernateSessionFactory.getSession();
    hTransaction=hsSession.beginTransaction();
    hCriteria=hSession.createCriteria(Employee.class);
    /*
    hCriteria.setFirstResult(to);
    hCriteria.setFirstResult(来自);
    */
    hCriteria.setResultTransformer(Criteria.DISTINCT\u ROOT\u实体);
    viewDataList=hCriteria.list();
    //限制
    exactDataList=viewDataList.subList(从、到);
    hTransaction.commit();
    }捕获(例外e){
    hTransaction.rollback();
    }最后{
    试一试{
    hSession.flush();
    HibernateSessionFactory.closeSession();
    }捕获(异常hExp){
    }
    }
    返回数据列表;
    }
    
    这是hibernate中的一个已知问题。查看@Cowan以获取生成的SQL和问题的解释。在他们的jira中有一个公开的bug请求。让我们希望有人来修理它:)


    您能添加hibernate映射和执行的SQL查询吗?Thomas,不幸的是,不能添加,因为它是一个非常复杂和深入的数据结构——即使是对于相关的POJO也是如此。我将尝试将问题隔离到一个较小的测试用例中,但您的响应可能是我问题的关键。是的,但我想知道的是,为什么它能与纯HQL查询一起工作(我们转而使用Criteria API)。我不太喜欢说明它可能与Hibernate的未来版本一起工作的文档,但是没有提到该文档是何时更新的,所以我不知道该案例是否仍然有效,因为它与HQL一起工作。据我所知,这个问题尚未解决。问得好。正是我需要的!是否有任何已知的(有效的)解决此问题的方法?这显然使我们无法使用标准API:(据我所知,这不是一个好方法。如果你没有处理大量的原始数据,你总是可以选择它们,使用
    DISTINCT\u ROOT\u ENTITY
    ,然后获取重新解析
    列表的前n项。不,不可伸缩,是的,很恶心。不幸的是,没有更好的建议——除非其他人知道在其他情况下,CriteriaAPI可能不适用于这种特殊情况