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

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

1. обзор

Эта статья иллюстрирует различные способыJPA can be used for sorting.

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

Spring Data JPA @Query

Узнайте, как использовать аннотацию @Query в Spring Data JPA для определения пользовательских запросов с использованием JPQL и собственного SQL.

Read more

JPA конвертеры атрибутов

Посмотрите на сопоставление типов JDBC с классами Java в JPA с помощью преобразователей атрибутов.

Read more

Работаем с Kotlin и JPA

Узнайте, как вы можете использовать JPA в своем проекте Kotlin.

Read more

2. Сортировка с помощью JPA / JQL API

Использование JQL для сортировки осуществляется с помощью предложенияOrder By:

String jql ="Select f from Foo as f order by f.id";
Query query = entityManager.createQuery (jql);

На основе этого запроса JPA генерирует следующие простыеSQL statement:

Hibernate: select foo0_.id as id1_4_, foo0_.name as name2_4_
    from Foo foo0_ order by foo0_.id

Обратите внимание, что ключевые слова SQL в строке JQL не чувствительны к регистру, но имена объектов и их атрибуты.

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

По умолчаниюthe sorting order is ascending, но его можно явно указать в строке JQL. Как и в чистом SQL, варианты упорядочения:asc иdesc:

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

Затемgenerated SQL query будет включать направление заказа:

Hibernate: select foo0_.id as id1_4_, foo0_.name as name2_4_
    from Foo foo0_ order by foo0_.id desc

2.2. Сортировка по более чем одному атрибуту

Для сортировки по нескольким атрибутам они добавляются в предложение order by строки JQL:

String jql ="Select f from Foo as f order by f.name asc, f.id desc";
Query sortQuery = entityManager.createQuery(jql);

Оба условия сортировки появятся в оператореgenerated SQL query:

Hibernate: select foo0_.id as id1_4_, foo0_.name as name2_4_
    from Foo foo0_ order by foo0_.name asc, foo0_.id desc

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

Приоритет значений NULL по умолчанию зависит от базы данных, но его можно настроить с помощью предложенияNULLS FIRST илиNULLS LAST в строке запроса HQL.

Вот простой пример - упорядочитьname изFoo в порядке убывания и разместитьNulls в конце:

Query sortQuery = entityManager.createQuery
    ("Select f from Foo as f order by f.name desc NULLS LAST");

Сгенерированный SQL-запрос включаетis null the 1 else 0 end clause (3-я строка):

Hibernate: select foo0_.id as id1_4_, foo0_.BAR_ID as BAR_ID2_4_,
    foo0_.bar_Id as bar_Id2_4_, foo0_.name as name3_4_,from Foo foo0_ order
    by case when foo0_.name is null then 1 else 0 end, foo0_.name desc

2.4. Сортировка отношений один ко многим

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

Мы хотим отсортировать сущностиBar, а также их коллекцию сущностейFoo - JPA особенно прост для этой задачи:

  1. Сортировка коллекции: добавьте аннотациюOrderBy перед коллекциейFoo в сущностиBar:

    @OrderBy("name ASC")
    List  fooList;
  2. Сортировка сущности, содержащей коллекцию:

    String jql = "Select b from Bar as b order by b.id";
    Query barQuery = entityManager.createQuery(jql);
    List barList = barQuery.getResultList();

Обратите внимание, что аннотация@OrderBy является необязательной, но мы используем ее в этом случае, потому что мы хотим отсортировать коллекциюFoo для каждогоBar.

Давайте посмотрим наSQL query, отправленные в RDMS:

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_ID2_0_0_, foolist0_.id as id1_4_0_,
foolist0_.id as id1_4_1_, foolist0_.BAR_ID as BAR_ID2_4_1_,
foolist0_.bar_Id as bar_Id2_4_1_, foolist0_.name as name3_4_1_
from Foo foolist0_
where foolist0_.BAR_ID=? order by foolist0_.name asc

Первый запрос сортирует родительскую сущностьBar. Второй запрос создается для сортировки коллекции дочерних сущностейFoo, принадлежащихBar.

3. Сортировка с помощью API объекта запроса критериев JPA

С критериями JPA - методorderBy является «универсальной» альтернативой для установки всех параметров сортировки: могут быть установлены какorder direction, так иattributes to sort by. Ниже приводится API метода:

  • orderBy (CriteriaBuilder.asc): сортировка по возрастанию.

  • orderBy (CriteriaBuilder.desc): сортировка по убыванию.

Каждый экземплярOrder создается с помощью объекта CriteriaBuilder с помощью его методовasc илиdesc.

Вот быстрый пример - сортировкаFoos по ихname:

CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Foo.class);
Root from = criteriaQuery.from(Foo.class);
CriteriaQuery select = criteriaQuery.select(from);
criteriaQuery.orderBy(criteriaBuilder.asc(from.get("name")));

Аргумент методаget чувствителен к регистру, так как он должен соответствовать имени атрибута.

В отличие от простого JQL, API-интерфейс объекта запроса критериев JPAforces an explicit order directionв запросе. Обратите внимание, что в последней строке этого фрагмента кода объектcriteriaBuilder указывает порядок сортировки по возрастанию, вызывая свой методasc.

Когда приведенный выше код выполняется, JPA генерирует SQL-запрос, показанный ниже. Объект критериев JPA генерирует оператор SQL с явным предложениемasc:

Hibernate: select foo0_.id as id1_4_, foo0_.name as name2_4_
    from Foo foo0_ order by foo0_.name asc

3.1. Сортировка по более чем одному атрибуту

Для сортировки по более чем одному атрибуту просто передайте экземплярOrder методуorderBy для каждого атрибута, по которому выполняется сортировка.

Вот быстрый пример - сортировка поname иid, в порядкеasc иdesc соответственно:

CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Foo.class);
Root from = criteriaQuery.from(Foo.class);
CriteriaQuery select = criteriaQuery.select(from);
criteriaQuery.orderBy(criteriaBuilder.asc(from.get("name")),
    criteriaBuilder.desc(from.get("id")));

Соответствующий SQL-запрос показан ниже:

Hibernate: select foo0_.id as id1_4_, foo0_.name as name2_4_
    from Foo foo0_ order by foo0_.name asc, foo0_.id desc

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

В этой статье рассматриваются альтернативы сортировки в Java Persistence API, для простых сущностей, а также для сущностей в отношении «один ко многим». Эти подходы делегируют бремя сортировки на уровень базы данных.

Реализация этого руководства по сортировке JPA можно найти вthe GitHub project - это проект на основе Maven, поэтому его должно быть легко импортировать и запускать как есть.