JPA Критерии Запросы

JPA Критерии Запросы

1. обзор

В этом руководстве мы обсудим очень полезную функцию JPA - запросы критериев.

Это не только позволяет нам писать запросы без использования исходного SQL, но также дает нам некоторый объектно-ориентированный контроль над запросами, который является одной из основных функций Hibernate. Criteria API позволяет нам создавать объект запроса критериев программно, где мы можем применять различные виды правил фильтрации и логических условий.

Since Hibernate 5.2, the Hibernate Criteria API is deprecated and new development is focused on the JPA Criteria API. Мы рассмотрим, как использовать Hibernate и JPA для создания критериальных запросов.

2. Maven Зависимости

Чтобы проиллюстрировать API, мы будем использовать эталонную реализацию JPA - Hibernate.

Чтобы использовать Hibernate, убедитесь, что вы добавили последнюю версию в свой файлpom.xml:


    org.hibernate
    hibernate-core
    5.3.2.Final

Последнюю версию Hibernate можно найтиhere.

3. Простой пример использования критериев

Начнем с того, что посмотрим, как получать данные с помощью критериев запросов. Мы посмотрим, как получить все экземпляры определенного класса из базы данных.

У нас есть классItem, который представляет кортеж“ITEM” в базе данных:

public class Item implements Serializable {

    private Integer itemId;
    private String itemName;
    private String itemDescription;
    private Integer itemPrice;

   // standard setters and getters
}

Давайте посмотрим на простой запрос по критериям, который извлечет все строки «ITEM” из базы данных:

Session session = HibernateUtil.getHibernateSession();
CriteriaBuilder cb = session.getCriteriaBuilder();
CriteriaQuery cr = cb.createQuery(Item.class);
Root root = cr.from(Item.class);
cr.select(root);

Query query = session.createQuery(cr);
List results = query.getResultList();

Приведенный выше запрос является простой демонстрацией того, как получить все предметы. Посмотрим, что было сделано, шаг за шагом:

  1. Создайте экземплярSession из объектаSessionFactory

  2. Создайте экземпляр CriteriaBuilder, вызвав методgetCriteriaBuilder()

  3. Создайте экземплярCriteriaQuery, вызвавCriteriaBuildercreateQuery() method

  4. Создайте экземплярQuery, вызвав методSessioncreateQuery()

  5. Вызвать методgetResultList() объектаquery, который даст нам результаты

Теперь, когда мы рассмотрели основы, давайте перейдем к некоторым функциям критериального запроса:

3.1. ИспользуяExpressions

The CriteriaBuilder can be used to restrict query results based on specific conditions. Используя методCriteriaQuery where() и предоставивExpressions, созданныйCriteriaBuilder.

Вот несколько примеров часто используемыхExpressions:

Чтобы получить предметы стоимостью более 1000:

cr.select(root).where(cb.gt(root.get("itemPrice"), 1000));

Затем получение элементов сitemPrice меньше 1000:

cr.select(root).where(cb.lt(root.get("itemPrice"), 1000));

Элементы сitemNames содержатChair:

cr.select(root).where(cb.like(root.get("itemName"), "%chair%"));

Записи сitemPrice между 100 и 200:

cr.select(root).where(cb.between(root.get("itemPrice"), 100, 200));

Чтобы проверить, является ли данное свойство нулевым:

cr.select(root).where(cb.isNull(root.get("itemDescription")));

Чтобы проверить, не является ли данное свойство нулевым:

cr.select(root).where(cb.isNotNull(root.get("itemDescription")));

Вы также можете использовать методыisEmpty() иisNotEmpty(), чтобы проверить, является лиList внутри класса пустым или нет.

Теперь неизбежно возникает вопрос, можем ли мы объединить два или более из приведенных выше сравнений или нет. Ответ, конечно, да -the Criteria API allows us to easily chain expressions:

Predicate[] predicates = new Predicate[2];
predicates[0] = cb.isNull(root.get("itemDescription"));
predicates[1] = cb.like(root.get("itemName"), "chair%");
cr.select(root).where(predicates);

Чтобы добавить два выражения с логическими операциями:

Predicate greaterThanPrice = cb.gt(root.get("itemPrice"), 1000);
Predicate chairItems = cb.like(root.get("itemName"), "Chair%");

Элементы с определенными выше условиями, объединенными сLogical OR:

cr.select(root).where(cb.or(greaterThanPrice, chairItems));

Чтобы получить элементы, соответствующие определенным выше условиям, объединенным сLogical AND:

cr.select(root).where(cb.and(greaterThanPrice, chairItems));

3.2. Сортировка

Теперь, когда мы знаем основы использованияCriteria, давайте взглянем на функции сортировкиCriteria.

В следующем примере мы упорядочиваем список в порядке возрастания имени, а затем в порядке убывания цены:

cr.orderBy(
  cb.asc(root.get("itemName")),
  cb.desc(root.get("itemPrice")));

В следующем разделе мы рассмотрим, как выполнять агрегатные функции.

3.3. Прогнозы, агрегаты и функции группировки

До сих пор мы рассмотрели большинство основных тем. Теперь давайте посмотрим на различные агрегатные функции:

Получить количество строк:

CriteriaQuery cr = cb.createQuery(Long.class);
Root root = cr.from(Item.class);
cr.select(cb.count(root));
Query query = session.createQuery(cr);
List itemProjected = query.getResultList();

Ниже приведен пример агрегатных функций:

ФункцияAggregate дляAverage:

CriteriaQuery cr = cb.createQuery(Double.class);
Root root = cr.from(Item.class);
cr.select(cb.avg(root.get("itemPrice")));
Query query = session.createQuery(cr);
List avgItemPriceList = query.getResultList();

Другие доступные методы агрегирования:sum(),max(),min(),count() и т. Д.

3.4. CriteriaUpdateс

Начиная с JPA 2.1, поддерживается выполнение обновлений базы данных с помощью APICriteria.

CriteriaUpdate имеет методset(), который можно использовать для предоставления новых значений для записей базы данных:

CriteriaUpdate criteriaUpdate = cb.createCriteriaUpdate(Item.class);
Root root = criteriaUpdate.from(Item.class);
criteriaUpdate.set("itemPrice", newPrice);
criteriaUpdate.where(cb.equal(root.get("itemPrice"), oldPrice));

Transaction transaction = session.beginTransaction();
session.createQuery(criteriaUpdate).executeUpdate();
transaction.commit();

В приведенном выше фрагменте мы создаем экземплярCriteriaUpdate<Item>  изCriteriaBuilder и используем его методset() для предоставления новых значений дляitemPrice.. Чтобы обновить несколько свойств, нам просто нужно вызовите методset() несколько раз.

3.5. CriteriaDeleteс

CriteriaDelete,, как следует из его названия, включает операцию удаления с использованием APICriteria. Все, что нам нужно, это создать экземплярCriteriaDelete и использовать методwhere() для применения ограничений:

CriteriaDelete criteriaDelete = cb.createCriteriaDelete(Item.class);
Root root = criteriaDelete.from(Item.class);
criteriaDelete.where(cb.greaterThan(root.get("itemPrice"), targetPrice));

Transaction transaction = session.beginTransaction();
session.createQuery(criteriaDelete).executeUpdate();
transaction.commit();

4. Преимущество перед HQL

В предыдущих разделах мы рассказали, как использовать критерии критериев.

Ясно, чтоthe main and most hard-hitting advantage of Criteria queries over HQL is the nice, clean, Object Oriented API.

Мы можем просто написать более гибкие, динамические запросы по сравнению с простым HQL. Логика может быть реорганизована с помощью IDE и имеет все преимущества безопасности типов в самом языке Java.

Конечно, есть и некоторые недостатки, особенно в отношении более сложных соединений.

Так что, вообще говоря, нам придется использовать лучший инструмент для работы - в большинстве случаев им может быть Criteria API, но определенно есть случаи, когда нам придется перейти на более низкий уровень.

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

В этой статье мы сосредоточились на основах Criteria Queries в Hibernate и JPA, а также на некоторых расширенных функциях API.

Обсуждаемый здесь код доступен вGithub repository.