我有一个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个结果,并且在数据库级别而不是在数据库级别进行不同的过滤,这似乎很疯狂。
帮助?
答案 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);