Как вы получаете "реальный" SQL отличается от запросов критериев гибернации? - PullRequest
3 голосов
/ 30 июня 2010

У меня есть запрос критериев Hibernate, который неправильно выводит максимальные результаты.Во многих случаях, когда я указываю 20 максимальных результатов, запрос на самом деле возвращает только 1 или 5 результатов, потому что ограничения возвращают много дубликатов.20 максимальных результатов, это действительно возвращает 20 районных результатов?Кажется довольно сумасшедшим, что hibernate ограничивает запрос до 20 результатов и выполняет отдельную фильтрацию AFTER вместо уровня базы данных.

Help?

Ответы [ 4 ]

7 голосов
/ 30 июня 2010

Я думаю, что вы близки, вам просто нужен список отдельных идентификаторов вместо, если отдельные объекты.

Попробуйте добавить это к вашим критериям:

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

Причина этогоработает потому, что проекция выполнит проверку четкости как часть запроса SQL вместо того, что ResultTransformer выполняет для фильтрации результатов на различимость после выполнения запроса SQL.

вышецитата из ответа на 300491

3 голосов
/ 15 февраля 2012

Я получил этот ответ с другого форума. Кажется, это лучшее решение.В основном вы сначала создаете подзапрос (DetachedCriteria).Это принесет все отличные идентификаторы.Затем вы применяете результаты этого подзапроса к своему основному запросу.

Полученный в результате 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 голосов
/ 30 июня 2010

Вы пытались использовать проекцию для идентификатора и создавать подзапрос на основе этих результатов, как описано на этой странице ?

РЕДАКТИРОВАТЬ: (Обратите внимание, что, похоже, ошибка в Oracle 11.2.0.1.0 , которая может помешать вам получить желаемые результаты, если вы используете это.)

0 голосов
/ 08 января 2013

Ниже приведен способ, которым мы можем сделать несколько проекций для выполнения 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;
   }

}

ExtraProjection.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

...