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

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

Как сортировать в JPA с помощью JQL или API критериев.

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

1. Обзор

Эта статья иллюстрирует различные способы использования JPA для сортировки .

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

Весенние данные JPA @Query

Преобразователи атрибутов JPA

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

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

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

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

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

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

2.1. Настройка порядка сортировки

По умолчанию порядок сортировки по возрастанию , но он может быть явно задан в строке JQL. Так же, как и в чистом SQL, параметры заказа являются asc и desc :

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

Затем сгенерированный SQL – запрос будет включать направление заказа:

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

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

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

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

Оба условия сортировки появятся в сгенерированном SQL-запросе инструкции:

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. Установка приоритета сортировки нулевых значений

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

Вот простой пример – упорядочение по name of Foo в порядке убывания и размещение Null s в конце:

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

Сгенерированный SQL-запрос включает в себя is null, затем 1 else 0 end предложение (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. Сортировка Отношений “Один Ко Многим”

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

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

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

  2. Сортировка сущности, содержащей коллекцию:

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

Давайте взглянем на SQL-запрос , отправленный в 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 является альтернативой “одной остановки” для установки всех параметров сортировки: можно задать как направление заказа , так и атрибуты для сортировки по. Ниже приведен API метода:

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

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

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

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

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

В отличие от простого JQL, API объекта запроса критериев JPA заставляет явное направление порядка в запросе. Обратите внимание в последней строке этого фрагмента кода, что объект criteries Builder задает порядок сортировки по возрастанию, вызывая свой метод 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 можно найти в проекте GitHub – это проект на основе Maven, поэтому его должно быть легко импортировать и запускать как есть.