Рубрики
Без рубрики

Сортировка с помощью Hibernate

Сортировка с помощью Hibernate 4 с помощью HQL или API критериев.

Автор оригинала: Eugen Paraschiv.

1. Обзор

Эта статья иллюстрирует как сортировать с помощью Hibernate , используя как язык запросов Hibernate (HQL), так и API критериев.

Дальнейшее чтение:

Hibernate: сохранение, сохранение, обновление, слияние, saveOrUpdate

Удаление объектов с помощью Hibernate

Спящие перехватчики

2. Сортировка С Помощью HQL

Сортировка с помощью HQL Hibernate так же проста, как добавление предложения Order By в строку запроса HQL:

String hql = "FROM Foo f ORDER BY f.name";
Query query = sess.createQuery(hql);

После выполнения этого кода Hibernate сгенерирует следующий SQL-запрос:

Hibernate: select foo0_.ID as ID1_0_, foo0_.NAME as NAME2_0_ from 
    FOO foo0_ order by foo0_.NAME

Направление сортировки по умолчанию-восходящее. Вот почему условие заказа, asc , не включается в сгенерированный SQL-запрос.

2.1. Использование явного Порядка сортировки

Чтобы указать порядок сортировки вручную – вам нужно будет включить направление заказа в строку запроса HQL :

String hql = "FROM Foo f ORDER BY f.name ASC";
Query query = sess.createQuery(hql);

В этом примере установка предложения asc в HQL была включена в сгенерированный SQL-запрос:

Hibernate: select foo0_.ID as ID1_0_, foo0_.NAME as NAME2_0_ 
    from FOO foo0_ order by foo0_.NAME ASC

2.2. Сортировка по Нескольким Атрибутам

Несколько атрибутов вместе с необязательным порядком сортировки могут быть добавлены в предложение Order By в строке запроса HQL:

String hql = "FROM Foo f ORDER BY f.name DESC, f.id ASC";
Query query = sess.createQuery(hql);

Сгенерированный SQL запрос будет соответствующим образом изменен:

Hibernate: select foo0_.ID as ID1_0_, foo0_.NAME as NAME2_0_ 
    from FOO foo0_ order by foo0_.NAME DESC, foo0_.ID ASC

2.3. Установка приоритета сортировки нулевых значений

По умолчанию, когда атрибут для сортировки имеет значения null , решение о приоритете принимается RDMS. Эту обработку по умолчанию можно переопределить, поместив предложение a NULLS FIRST или NULLS LAST в строку запроса HQL .

Этот простой пример помещает любые нули в конец списка результатов:

String hql = "FROM Foo f ORDER BY f.name NULLS LAST";
Query query = sess.createQuery(hql);

Давайте посмотрим, что is null then 1 else 0 предложение в сгенерированном SQL-запросе :

Hibernate: select foo0_.ID as ID1_1_, foo0_.NAME as NAME2_1_, 
foo0_.BAR_ID as BAR_ID3_1_, foo0_.idx as idx4_1_ from FOO foo0_ 
order by case when foo0_.NAME is null then 1 else 0 end, foo0_.NAME

2.4. Сортировка От Одного Ко Многим Отношениям

Давайте проанализируем сложный случай сортировки: сортировка сущностей в отношении один ко многимBar , содержащем коллекцию сущностей Foo .

Мы сделаем это, аннотируя коллекцию с помощью Hibernate @OrderBy annotation ; мы укажем поле, по которому выполняется заказ, а также направление:

@OrderBy(clause = "NAME DESC")
Set fooList = new HashSet();

Обратите внимание, что предложение аргумент аннотации. Это уникально для Hibernate @OrderBy , по сравнению с аналогичной аннотацией @OrderBy JPA. Еще одна характеристика, отличающая этот подход от его эквивалента GPA, заключается в том, что аргумент clause указывает, что сортировка выполняется на основе столбца NAME таблицы FOO , а не на атрибуте name таблицы Foo .

Теперь давайте посмотрим на фактическую сортировку Баров и Еды :

String hql = "FROM Bar b ORDER BY b.id";
Query query = sess.createQuery(hql);

Результирующий SQL-оператор показывает, что сортированные Foo помещаются в глупый:

Hibernate: select bar0_.ID as ID1_0_, bar0_.NAME as NAME2_0_ from BAR bar0_ 
    order by bar0_.ID Hibernate: select foolist0_.BAR_ID as BAR_ID3_0_0_, 
    foolist0_.ID as ID1_1_0_, foolist0_.ID as ID1_1_1_, foolist0_.NAME as 
    NAME2_1_1_, foolist0_.BAR_ID as BAR_ID3_1_1_, foolist0_.idx as idx4_1_1_ 
    from FOO foolist0_ where foolist0_.BAR_ID=? order by foolist0_.NAME desc

Следует иметь в виду, что сортировка списков невозможна, как это было в случае с JPA. Состояния документации Hibernate:

“Hibernate в настоящее время игнорирует @OrderBy на @ElementCollection, например, List. Порядок элементов, возвращаемый базой данных, не определен.”

В качестве дополнительного замечания можно было бы обойти это ограничение, используя устаревшую конфигурацию XML для Hibernate и заменив элемент с <Сумка…> элемент.

3. Сортировка По Критериям Hibernate

API объекта критериев предоставляет класс Order в качестве основного API для управления сортировкой.

3.1. Установка порядка сортировки

Класс Order имеет два метода для установки порядка сортировки:

  • asc (String attribute) : Сортирует запрос по attribute в порядке возрастания.
  • desc (String attribute) : Сортирует запрос по attribute в порядке убывания.

Начнем с простого примера – сортировки по одному id атрибуту:

Criteria criteria = sess.createCriteria(Foo.class, "FOO");
criteria.addOrder(Order.asc("id"));

Обратите внимание, что аргумент метода asc чувствителен к регистру и должен соответствовать name атрибута для сортировки.

Hibernate Criteries Object API явно задает направление порядка сортировки, и это отражается в SQL-операторе, сгенерированном кодом:

Hibernate: select this_.ID as ID1_0_0_, this_.NAME as NAME2_0_0_ 
    from FOO this_ order by this_.ID sac

3.2. Сортировка по Нескольким Атрибутам

Сортировка по нескольким атрибутам требует только добавления объекта Order в экземпляр Criteries , как в приведенном ниже примере:

Criteria criteria = sess.createCriteria(Foo.class, "FOO");
criteria.addOrder(Order.asc("name"));
criteria.addOrder(Order.asc("id"));

Запрос, который генерируется в SQL, является:

Hibernate: select this_.ID as ID1_0_0_, this_.NAME as NAME2_0_0_ from 
    FOO this_ order by this_.NAME asc, this_.ID sac

3.3. Установка приоритета сортировки нулевых значений

По умолчанию, когда атрибут для сортировки имеет значения null , решение о приоритете принимается RDMS. Hibernate Criteries Object API упрощает изменение этого значения по умолчанию и помещает нули в конец упорядоченного по возрастанию списка:

Criteria criteria = sess.createCriteria(Foo.class, "FOO");
criteria.addOrder(Order.asc("name").nulls(NullPrecedence.LAST));

Вот базовый SQL запрос – с предложением is null then 1 else 0 :

Hibernate: select this_.ID as ID1_1_1_, this_.NAME as NAME2_1_1_, 
    this_.BAR_ID as BAR_ID3_1_1_, this_.idx as idx4_1_1_, bar2_.ID as
    ID1_0_0_, bar2_.NAME as NAME2_0_0_ from FOO order by case when 
    this_.NAME is null then 1 else 0 end, this_.NAME asc

В качестве альтернативы мы также можем поместить нули в начало нисходящего упорядоченного списка:

Criteria criteria = sess.createCriteria(Foo.class, "FOO");
criteria.addOrder(Order.desc("name").nulls(NullPrecedence.FIRST));

Соответствующий SQL – запрос следует-с предложением is null then 0 else 1 :

Hibernate: select this_.ID as ID1_1_1_, this_.NAME as NAME2_1_1_, 
    this_.BAR_ID as BAR_ID3_1_1_, this_.idx as idx4_1_1_, bar2_.ID as 
    ID1_0_0_, bar2_.NAME as NAME2_0_0_ from FOO order by case when 
    this_.NAME is null then 0 else 1 end, this_.NAME desc

Обратите внимание, что если атрибут для сортировки является примитивным типом, таким как int, a Persistenceexception будет брошен .

Например, если значение f.an Int переменная имеет значение null, то выполнение запроса:

String jql = "Select f from Foo as f order by f.anIntVariable desc NULLS FIRST";
Query sortQuery = entityManager.createQuery(jql);

будет бросать:

javax.persistence.PersistenceException: org.hibernate.PropertyAccessException:
Null value was assigned to a property of primitive type setter of 
com.cc.jpa.example.Foo.anIntVariable

4. Заключение

В этой статье рассматривается сортировка с помощью Hibernate – использование доступных API для простых сущностей, а также для сущностей в отношении “один ко многим”.

Реализацию этого учебника по сортировке Hibernate можно найти в проекте github – это проект на основе Eclipse, поэтому его должно быть легко импортировать и запускать как есть.