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

Сортировка с Hibernate

1. обзор

В этой статье показанhow to Sort with Hibernate с использованием как языка запросов Hibernate (HQL), так и API критериев.

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

Hibernate: сохранить, сохранить, обновить, объединить, saveOrUpdate

Краткое и практическое руководство по методам записи Hibernate: сохранение, сохранение, обновление, объединение, saveOrUpdate.

Read more

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

Краткое руководство по удалению сущности в Hibernate.

Read more

Hibernate Перехватчики

Краткое и практическое руководство по созданию перехватчиков Hibernate.

Read more

2. Сортировка с HQL

Сортировка с помощью Hibernate HQL так же проста, как добавление предложения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 or NULLS LAST clause in the HQL query string.

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

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

Давайте посмотрим предложениеis null then 1 else 0 вgenerated SQL query:

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. Сортировка отношений один ко многим

Давайте проанализируем сложный случай сортировки:sorting entities in a one to many relation -Bar, содержащий набор сущностейFoo.

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

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

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

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

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

resulting SQL statement показывает, что отсортированныеFoo’s помещаются вfooList:

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

Следует иметь в виду, что этоnot possible to to sort Lists, как в случае с JPA. Документация Hibernate гласит:

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

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

3. Сортировка по критериям гибернации

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 атрибута для сортировки.

Object API Hibernate Criteria явно устанавливает направление сортировки, и это отражается в операторе 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 к экземпляруCriteria, как в примере ниже:

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 Criteria Object API упрощает изменение этого значения по умолчанию иplace nulls at the end в возрастающем упорядоченном списке:

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

В качестве альтернативы мы также можемplace the nulls at the beginning упорядоченного по убыванию списка:

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

Отметим, чтоif the attribute to sort by is a primitive type like an int, a PresisitenceException will thrown.

Например, если значениеf.anIntVariable равно нулю, то выполнение запроса:

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 можно найти вthe github project - это проект на основе Eclipse, поэтому его должно быть легко импортировать и запускать как есть.