如何获得“真实”的体验? sql 与 hibernate 标准查询不同吗?

发布于 2024-09-07 23:05:36 字数 594 浏览 5 评论 0原文

我有一个 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 个结果,并在之后而不是在数据库级别进行不同的过滤,这似乎非常疯狂。

帮助?

I have a Hibernate criteria query that is incorrectly pulling out max results. In many cases, when I specify 20 max results, the query actually only returns 1 or 5 results, because the restrictions return many duplicates.

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();

Is there any way to fix this query so that if I say 20 max results, it really does return 20 district results? It seems pretty crazy that hibernate limits the query to 20 results, and does the distinct filtering AFTER instead of at the database level.

Help?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

溺ぐ爱和你が 2024-09-14 23:05:36

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

尝试将此添加到您的标准中:

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

这样做的原因是因为
投影将执行
唯一性检查作为 sql 的一部分
查询,而不是什么
ResultTransformer 的作用是
过滤结果的清晰度
sql查询完成后
已执行。

以上是 300491

I think you are close, you just need a list of distinct Ids instead if distinct objects.

Try adding this to your criteria:

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

The reason this works is because the
projection will perform the
distinctness check as part of the sql
query, instead of what a
ResultTransformer does which is to
filter the results for distinctness
after the sql query has been
performed.

the above is a quote from the answer at 300491

失眠症患者 2024-09-14 23:05:36

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

I got this answer from another forum
It appears to be the best solution. Basically you create a subquery first (the DetachedCriteria). This will fetch all the distinct ids.
Then, you apply the results of that subquery to your main query.

The resulting SQL generated by this is quite clean, and hibernate returns the results to you as a list of objects.

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")));
清风挽心 2024-09-14 23:05:36

您是否尝试过在 ID 上使用投影并根据这些结果创建子查询,如 此页面

编辑:(请注意,Oracle 11.2.0.1.0 中似乎存在 一个错误 如果您正在使用的话,这可能会阻止您获得您想要的结果。)

Have you tried to use a Projection on the ID and create a subquery based on those results, as described on this page?

EDIT: (Note that there seems to be a bug in Oracle 11.2.0.1.0 which may prevent you from getting the results you want if that's what you're using.)

月下伊人醉 2024-09-14 23:05:36

下面是我们可以通过多重投影来执行 Distinct

    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

Below is the way we can do Multiple projection to perform Distinct

    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();
    }
}

Sample Usage:

String propertyNames = "titleName;titleDescr;titleVersion"

criteria countCriteria = ....

countCriteria.setProjection(ExtraProjections.countMultipleDistinct(propertyNames);

Referenced from https://forum.hibernate.org/viewtopic.php?t=964506

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文