1. Общий обзор
В этой статье показаны различные способы использования JPA для сортировки.
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:
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. Сортировка по нескольким признакам
Для сортировки по нескольким атрибутам они добавляются в предложение order 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. Установка приоритета сортировки нулевых значений
Приоритет значений null по умолчанию зависит от базы данных, но его можно настроить с помощью предложения NULLS FIRST или NULLS LAST в строке запроса HQL.
Вот простой пример – упорядочивание по имени Foo в порядке убывания и размещение значений Null в конце:
Query sortQuery = entityManager.createQuery
("Select f from Foo as f order by f.name desc NULLS LAST");
Сгенерированный SQL-запрос содержит предложение is null then 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. Сортировка отношений "От одного ко Многим"
Перейдя к основным примерам, давайте теперь рассмотрим вариант использования, связанный с сортировкой объектов в строке отношения "один ко многим", содержащей коллекцию объектов Foo.
Мы хотим отсортировать объекты Bar, а также их коллекцию объектов Foo – JPA особенно прост для этой задачи:
1. Сортировка коллекции: добавьте аннотацию OrderBy, предшествующую коллекции Foo, в объект Bar:
@OrderBy("name ASC")
List <Foo> fooList;
2. Сортировка объекта, содержащего коллекцию:
String jql = "Select b from Bar as b order by b.id";
Query barQuery = entityManager.createQuery(jql);
List<Bar> barList = barQuery.getResultList();
Обратите внимание, что аннотация @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. Сортировка с помощью JPA Criteria Query Object API
В соответствии с критериями JPA метод OrderBy – это универсальная альтернатива для настройки всех параметров сортировки: можно задать как направление сортировки, так и атрибуты для сортировки. Ниже приведен API метода:
- orderBy(CriteriaBuilder.asc): Отсортированы в порядке возрастания.
- orderBy(CriteriaBuilder.desc): Отсортированы в порядке убывания.
Каждый экземпляр заказа создается с помощью объекта Criteria Builder с помощью методов asc или desc.
Вот краткий пример – сортировка объектов по их названию:
CriteriaQuery<Foo> criteriaQuery = criteriaBuilder.createQuery(Foo.class);
Root<Foo> from = criteriaQuery.from(Foo.class);
CriteriaQuery<Foo> select = criteriaQuery.select(from);
criteriaQuery.orderBy(criteriaBuilder.asc(from.get("name")));
Аргумент метода get чувствителен к регистру, поскольку он должен совпадать с именем атрибута.
В отличие от простого JQL, API объекта запроса критериев JPA использует явное указание порядка в запросе. Обратите внимание, что в последней строке этого фрагмента кода объект criteria Builder определяет порядок сортировки по возрастанию, вызывая свой метод asc.
При выполнении приведенного выше кода JPA генерирует SQL-запрос, показанный ниже. Объект JPA Criteria генерирует 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 для сортировки по каждому атрибуту.
Вот краткий пример – сортировка по имени и идентификатору в порядке возрастания и убывания, соответственно:
CriteriaQuery<Foo> criteriaQuery = criteriaBuilder.createQuery(Foo.class);
Root<Foo> from = criteriaQuery.from(Foo.class);
CriteriaQuery<Foo> 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 как для простых объектов, так и для объектов в соотношении "один ко многим". Эти подходы делегируют бремя сортировки на уровень базы данных.
Оригинал статьи: https://www.baeldung.com/jpa-sort