首页 文章

你如何通过hibernate条件查询得到“真正的”sql?

提问于
浏览
3

我有一个Hibernate条件查询错误地提取最大结果 . 在许多情况下,当我指定20个最大结果时,查询实际上只返回1或5个结果,因为限制会返回许多重复项 .

Criteria c = session.createCriteria(DomainObject.class);
c.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
c.createAlias("tags.list", "tag");
c.createAlias("names", "name");
c.createAlias("site", "site");
c.createAlias("site.tags.list", "siteTag");

// loads of or/and eq/like restrictions.

c.setFirstResult(0);
c.setMaxResults(20);

return c.list();

有没有办法解决这个问题,以便如果我说20个最大结果,它确实会返回20区结果? hibernate将查询限制为20个结果,并且在数据库级别而不是在数据库级别进行不同的过滤,这似乎很疯狂 .

救命?

4 回答

  • 7

    我认为你很接近,你只需要一个不同的ID列表,而不是不同的对象 .

    尝试将此添加到您的条件:

    criteria.setProjection(Projections.distinct(Projections.property("Id")));
    

    这个工作的原因是因为投影将执行清晰度检查作为sql查询的一部分,而不是ResultTransformer在执行sql查询后过滤结果的清晰度 .

    以上是答案的引用300491

  • 0

    我从另一个论坛得到了这个答案它似乎是最好的解决方案 . 基本上你首先创建一个子查询(DetachedCriteria) . 这将获取所有不同的ID . 然后,将该子查询的结果应用于主查询 .

    由此生成的结果SQL非常干净,而hibernate将结果作为对象列表返回给您 .

    Criteria criteria = session().createCriteria(Employee.class);
    criteria.add(Property.forName("id").in(dc)); 
    criteria.setMaxResults(maxLength);
    criteria.setFirstResult((int)rowNum);
    
    
    DetachedCriteria dc = DetachedCriteria.forClass(Employee.class);
    dc.createAlias("location", "location");
    dc.createAlias("location.dept", "department");
    dc.add(
        Restrictions.or(
            Restrictions.eq("location.id", locationId),
            Restrictions.eq("department.name", departmentName)));
    dc.setProjection(Projections.distinct(Property.forName("id")));
    
  • 2

    您是否尝试在ID上使用Projection并根据这些结果创建子查询,如this page所述?

    编辑:(注意,如果's what you'正在使用,似乎有a bug in Oracle 11.2.0.1.0可能会阻止您获得所需的结果 . )

  • 3

    以下是我们可以执行多项投影以执行区别的方式

    package org.hibernate.criterion;
    
    import org.hibernate.Criteria;
    import org.hibernate.Hibernate;
    import org.hibernate.HibernateException;
    import org.hibernate.type.Type;
    
    /**
    * A count for style :  count (distinct (a || b || c))
    * @author Deepak Surti
    */
    public class MultipleCountProjection extends AggregateProjection {
    
       private boolean distinct;
    
       protected MultipleCountProjection(String prop) {
          super("count", prop);
       }
    
       public String toString() {
          if(distinct) {
             return "distinct " + super.toString();
          } else {
             return super.toString();
          }
       }
    
       public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery) 
       throws HibernateException {
          return new Type[] { Hibernate.INTEGER };
       }
    
       public String toSqlString(Criteria criteria, int position, CriteriaQuery criteriaQuery) 
       throws HibernateException {
          StringBuffer buf = new StringBuffer();
          buf.append("count(");
          if (distinct) buf.append("distinct ");
            String[] properties = propertyName.split(";");
            for (int i = 0; i < properties.length; i++) {
               buf.append( criteriaQuery.getColumn(criteria, properties[i]) );
                 if(i != properties.length - 1) 
                    buf.append(" || ");
            }
            buf.append(") as y");
            buf.append(position);
            buf.append('_');
            return buf.toString();
       }
    
       public MultipleCountProjection setDistinct() {
          distinct = true;
          return this;
       }
    
    }
    

    ExtraProjections.java

    package org.hibernate.criterion; 
    
    public final class ExtraProjections
    { 
        public static MultipleCountProjection countMultipleDistinct(String propertyNames) {
            return new MultipleCountProjection(propertyNames).setDistinct();
        }
    }
    

    样品用法:

    String propertyNames = "titleName;titleDescr;titleVersion"
    
    criteria countCriteria = ....
    
    countCriteria.setProjection(ExtraProjections.countMultipleDistinct(propertyNames);
    

    参考自https://forum.hibernate.org/viewtopic.php?t=964506

相关问题