Как создать отчетливый запрос в HQL

100

Есть ли способ создать отчетливый запрос в HQL. Либо с помощью ключевого слова «отличное», либо каким-либо другим способом. Я не уверен, является ли отличная ключевая работа для HQL допустимой, но я ищу HQL-эквивалент ключевого слова SQL «отличная».

Майк Поун
источник

Ответы:

124

Вот фрагмент кода hql, который мы используем. (Имена изменены для защиты личности)

String queryString = "select distinct f from Foo f inner join foo.bars as b" +
                " where f.creationDate >= ? and f.creationDate < ? and b.bar = ?";
        return getHibernateTemplate().find(queryString, new Object[] {startDate, endDate, bar});
Ноги
источник
Я когда-либо использовал спящий режим только с MySQL - не знаю, как решить проблему с mssql.
Feet
Функция getHibernateTemplate () принадлежит Spring Framework, а не стандартному API. Вы знаете эквивалент без использования Spring Framework?
Matthieu.
56

Стоит отметить, что distinctключевое слово в HQL не отображается напрямую на distinctключевое слово в SQL.

Если вы используете distinctключевое слово в HQL, то иногда Hibernate будет использовать distinctключевое слово SQL, но в некоторых ситуациях он будет использовать преобразователь результатов для получения четких результатов. Например, когда вы используете такое внешнее соединение:

select distinct o from Order o left join fetch o.lineItems

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

Даниэль Алексюк
источник
1
Ответ здесь: stackoverflow.com/questions/5471819/…
Daniel Alexiuc
16

сделай что-нибудь подобное в следующий раз

 Criteria crit = (Criteria) session.
                  createCriteria(SomeClass.class).
                  setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

 List claz = crit.list();
Майкл
источник
1
Это неоптимально: вместо того, чтобы отбрасывать повторы на уровне базы данных, он просто извлекает данные из базы данных в память с повторениями и всем остальным, а затем отбрасывает повторения; в зависимости от того, как часто данные повторяются, это может значительно увеличить количество операций ввода-вывода.
Haroldo_OK
9

Вы также можете использовать Criteria.DISTINCT_ROOT_ENTITYHibernate HQL-запрос.

Пример:

Query query = getSession().createQuery("from java_pojo_name");
query.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
return query.list();
aadi53
источник
1
Это неоптимально: вместо того, чтобы отбрасывать повторы на уровне базы данных, он просто извлекает данные из базы данных в память с повторениями и всем остальным, а затем отбрасывает повторения; в зависимости от того, как часто данные повторяются, это может значительно увеличить количество операций ввода-вывода.
Haroldo_OK
4

У меня были проблемы с преобразователями результатов в сочетании с HQL-запросами. Когда я попробовал

final ResultTransformer trans = new DistinctRootEntityResultTransformer();
qry.setResultTransformer(trans);

это не сработало. Пришлось трансформировать вручную вот так:

final List found = trans.transformList(qry.list());

Трансформаторы Criteria API работали нормально.

Тадеуш Копец
источник
чтобы добраться до 10к (:
timmz 02
3

Мой основной запрос в модели выглядел так:

@NamedQuery(name = "getAllCentralFinancialAgencyAccountCd", 
    query = "select distinct i from CentralFinancialAgencyAccountCd i")

И я все еще не получал того, что я считал «отчетливым». Они просто отличались на основе комбинации первичных ключей в таблице.

Итак, DaoImplя добавил одну строчку и в итоге получил желаемый "отчетливый" результат. Например, вместо того, чтобы увидеть 00 четыре раза, теперь я вижу его только один раз. Вот код, который я добавил в DaoImpl:

@SuppressWarnings("unchecked")
public List<CacheModelBase> getAllCodes() {

    Session session = (Session) entityManager.getDelegate();
    org.hibernate.Query q = session.getNamedQuery("getAllCentralFinancialAgencyAccountCd");
    q.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); // This is the one line I had to add to make it do a more distinct query.
    List<CacheModelBase> codes;
    codes = q.list();
    return codes;       
}

Надеюсь, это помогло! Опять же, это может сработать только в том случае, если вы следуете методам программирования, которые реализуют сервис, дао и тип проекта.

Натан Митчелл
источник
2

Предположим, у вас есть сущность клиента, сопоставленная с таблицей CUSTOMER_INFORMATION, и вы хотите получить список отдельных firstName клиента. Вы можете использовать приведенный ниже фрагмент, чтобы получить то же самое.

Query distinctFirstName = session.createQuery("select ci.firstName from Customer ci group by ci.firstName");
Object [] firstNamesRows = distinctFirstName.list();

Я надеюсь, что это помогает. Итак, здесь мы используем group by вместо использования отдельного ключевого слова.

Также ранее мне было трудно использовать отдельное ключевое слово, когда я хочу применить его к нескольким столбцам. Например, я хочу получить список отдельных firstName, lastName, а затем group by будет просто работать. В этом случае у меня возникли трудности с использованием отличного.

чамму
источник
1

У меня есть ответ на использование языка запросов Hibernate для использования разных полей. Вы можете использовать * SELECT DISTINCT (TO_CITY) FROM FLIGHT_ROUTE *. Если вы используете SQL- запрос, он возвращает список строк. Вы не можете использовать его возвращаемое значение по классу сущности. Итак, ответ для решения такой проблемы - использовать HQL с SQL .

FROM FLIGHT_ROUTE F WHERE F.ROUTE_ID IN (SELECT SF.ROUTE_ID FROM FLIGHT_ROUTE SF GROUP BY SF.TO_CITY);

Из оператора запроса SQL он получил DISTINCT ROUTE_ID и введен в виде списка. И запрос IN фильтрует отдельный TO_CITY из IN (List).

Тип возврата - тип Entity Bean. Таким образом, вы можете использовать AJAX, например AutoComplement .

Может все будет хорошо

Сан Линь Наинг
источник
1

Вы можете использовать ключевое слово в своем конструкторе критериев следующим образом.

CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaQuery<Orders> query = builder.createQuery(Orders.class);
Root<Orders> root = query.from(Orders.class);
query.distinct(true).multiselect(root.get("cust_email").as(String.class));

И создайте конструктор поля в своем классе модели.

Сантош Сингх
источник
0

Если вам нужно использовать ключевое слово new для настраиваемого DTO в операторе select и вам нужны отдельные элементы , используйте new за пределами new, например, следующим образом:

select distinct new com.org.AssetDTO(a.id, a.address, a.status) from Asset as a where ...
Маниш Шарма
источник
0

Вы можете просто добавить GROUP BY вместо Distinct

@Query(value = "from someTableEntity where entityCode in :entityCode" +
            " group by entityCode, entityName, entityType")
List<someTableEntity > findNameByCode(@Param("entityCode") List<String> entityCode);
Рустем
источник