Сортування за допомогою Hibernate

1. Огляд

У цій статті показано, як сортувати за допомогою Hibernate , використовуючи як мову запитів Hibernate (HQL), так і API критеріїв.

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. Встановлення пріоритету сортування нульових значень

За замовчуванням, коли атрибут для сортування має нульові значення, RDMS визначає пріоритет. Ця обробка по замовчуванням може бути перевизначена шляхом розміщення в NULLS ПЕРШОЇ або NULLS ОСТАННЬОГО пункту в рядку HQL запитів .

Цей простий приклад розміщує будь-які нулі в кінці списку результатів:

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

Давайте переглянемо речення null, а потім 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. Сортування відносин один до багатьох

Давайте проаналізуємо складний випадок сортування: сортування сутностей у відношенні один до багатьох - панель, що містить колекцію сутностей Foo .

Ми зробимо це, анотуючи колекцію анотацією Hibernate @OrderBy ; ми вкажемо поле, за яким здійснюється впорядкування, а також напрямок:

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

Зверніть увагу на аргумент цього речення до анотації. Це унікально для @OrderBy Hibernate , порівняно з аналогічною анотацією @OrderBy JPA. Ще однією характеристикою, яка відрізняє цей підхід від його еквівалента JPA, є те, що аргумент пропозиції вказує, що сортування здійснюється на основі стовпця NAME таблиці FOO , а не на основі атрибута name Foo .

А тепер давайте розглянемо фактичне сортування Bars and Foos :

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

В результаті SQL заяву показує , що впорядковані Foo ігровими поміщають в 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

Майте на увазі одне, що неможливо сортувати Списки, як це було у випадку з JPA. Документація про сплячий режим говорить:

“Hibernate наразі ігнорує @OrderBy у @ElementCollection у, наприклад, списку. Порядок елементів такий, що повертається базою даних, невизначений. "

Як зауваження, можливо, можна обійти це обмеження, використовуючи застарілу конфігурацію XML для Hibernate та замінюючи елемент з a елемент.

3. Сортування за критеріями сплячого режиму

API Criteria Object надає клас Order як основний API для управління сортуванням.

3.1. Встановлення порядку сортування

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

  • asc (атрибут рядка) : сортує запит за атрибутом у порядку зростання.
  • desc (атрибут String) : сортує запит за атрибутом у порядку зменшення.

Почнемо з простого прикладу - сортування за одним атрибутом id :

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

Зверніть увагу, що аргумент методу asc чутливий до регістру і повинен відповідати імені атрибута, за яким потрібно сортувати.

Об’єктний 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 до екземпляра 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. Встановлення пріоритету сортування нульових значень

By default, when the attribute to sort by has null values, it is up to the RDMS to decide the precedence. Hibernate Criteria Object API makes it simple to change that default and place nulls at the end of an ascending ordered list:

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

Here is the underlying SQL query – with the is null then 1 else 0 clause:

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

Alternatively, we can also place the nulls at the beginning of a descending ordered list:

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

The corresponding SQL query follows – with the is null then 0 else 1 clause:

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

Note that, 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 для простих сутностей, а також для сутностей, що мають відношення один до багатьох.

Реалізацію цього підручника з сортування в сплячому режимі можна знайти в проекті github - це проект на основі Eclipse, тому його слід легко імпортувати та запускати як є.