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

时间:2010-06-30 00:58:41

标签: hibernate max criteria

我有一个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 个答案:

答案 0 :(得分:7)

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

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

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

这是有效的原因是因为   投影将执行   清晰度检查作为SQL的一部分   查询,而不是什么   ResultTransformer做的是   过滤结果以获得清晰度   在sql查询之后   进行。

以上是300491

答案的引用

答案 1 :(得分:3)

我从另一个论坛得到了这个答案 这似乎是最好的解决方案。基本上你首先创建一个子查询(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 :(得分:2)

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

编辑:(请注意,似乎a bug in Oracle 11.2.0.1.0可能会阻止您获得所需的结果,如果这就是您正在使用的结果。)

答案 3 :(得分:0)

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

的方式
    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