В этом уроке мы узнаем, как проецировать свойства сущностей с помощью JPA и Hibernate .
2. Сущность
Во-первых, давайте рассмотрим сущность, которую мы будем использовать на протяжении всей этой статьи:
@Entity
public class Product {
@Id
private long id;
private String name;
private String description;
private String category;
private BigDecimal unitPrice;
// setters and getters
}
Это простой класс сущностей, представляющий продукт с различными свойствами.
3. Проекции JPA
В спецификации JPA явно не упоминаются проекции, есть много случаев, когда мы находим их в концепции.
Как правило, запрос JPQL имеет класс сущностей-кандидатов. Запрос при выполнении создает объекты класса — кандидата, заполняя все их свойства с использованием полученных данных.
Но можно получить подмножество свойств сущности, или, то есть проекцию данных столбца.
Помимо данных столбцов, мы также можем проецировать результаты функций группировки.
3.1. Одноколоночные проекции
Предположим, мы хотим перечислить названия всех продуктов. В JPQL мы можем сделать это, включив только name в предложение select :
Query query = entityManager.createQuery("select name from Product");
List
Или мы можем сделать то же самое с CriteriaBuilder :
Поскольку мы проецируем один столбец , который имеет типString, мы ожидаем получить списокStrings в результате. Следовательно, мы указали класс-кандидат как String в методе CreateQuery () .
Поскольку мы хотим проецировать на одно свойство, мы использовали методQuery.select (). Здесь идет речь о том, какое свойство нам нужно, поэтому в нашем случае мы будем использовать имя свойство из нашего Продукта сущности.
Теперь давайте рассмотрим пример вывода, сгенерированный двумя приведенными выше запросами:
Product Name 1
Product Name 2
Product Name 3
Product Name 4
Обратите внимание , что если бы мы использовали свойствоidв проекции вместоname, запрос вернул бы списокLongобъектов.
3.2. Многоколоночные проекции
Чтобы спроецировать несколько столбцов с помощью JPQL, нам нужно только добавить все необходимые столбцы в предложение select :
Query query = session.createQuery("select id, name, unitPrice from Product");
List resultList = query.getResultList();
Но при использовании Построителя критериев нам придется действовать немного по-другому:
Здесь/| мы использовали метод multiselect()вместоselect(). Используя этот метод, мы можем указать несколько элементов для выбора.
Еще одним существенным изменением является использование Object[] . Когда мы выбираем несколько элементов, запрос возвращает массив объектов со значением для каждого проецируемого элемента. Это относится и к JPQL.
Давайте посмотрим, как выглядят данные, когда мы их печатаем:
[1, Product Name 1, 1.40]
[2, Product Name 2, 4.30]
[3, Product Name 3, 14.00]
[4, Product Name 4, 3.90]
Как мы видим, возвращаемые данные немного громоздки для обработки. Но, к счастью, мы можем заставить JPAзаполнить эти данные в пользовательский класс.
Кроме того, мы можем использовать CriteriaBuilder.tuple() или Criteriabuilder.construct() для получения результатов в виде списка объектов Tuple или объектов пользовательского класса соответственно.
3.3. Проектирование Агрегатных Функций
Помимо данных столбцов, иногда нам может потребоваться сгруппировать данные и использовать агрегатные функции, такие как count и average.
Допустим, мы хотим найти количество продуктов в каждой категории. Мы можем сделать это с помощью функции count() aggregate в JPQL:
Query query = entityManager.createQuery("select p.category, count(p) from Product p group by p.category");
Здесь мы использовали метод Criteries Builder ‘s count () .
Использование любого из вышеперечисленных способов приведет к созданию списка массивов объектов:
[category1, 2]
[category2, 1]
[category3, 1]
Помимо count() , Criteria Builder предоставляет различные другие агрегатные функции:
avg – Вычисляет среднее значение для столбца в группе
max – Вычисляет максимальное значение для столбца в группе
min – Вычисляет минимальное значение для столбца в группе
наименьшее – Находит наименьшее значение столбца (например, в алфавитном порядке или по дате)
sum – Вычисляет сумму значений столбцов в группе
4. Спящий режим Проекций
В отличие от JPA, Hibernate предоставляет org.hibernate.criterion.Проекциядля проектирования с запросомКритериев . Он также предоставляет класс с именем org.hibernate.criterion.Проекции, фабрика для Проекции экземпляров.
4.1. Одностолбчатые проекции
Во-первых, давайте посмотрим, как мы можем спроецировать один столбец. Мы будем использовать пример, который мы видели ранее:
Мы использовали метод Criteries.setProjection () , чтобы указать свойство, которое мы хотим получить в результате запроса. Projections.property()выполняет для нас ту же работу, что иRoot.get()делал при указании столбца для выбора.
4.2. Многоколоночные проекции
Чтобы спроецировать несколько столбцов, нам сначала нужно создать список проекций .Список проекций– это особый видПроекции, который обертывает другие проекции для выбора нескольких значений .
Мы можем создать Список проекцийс помощью методаProjections.ProjectionList () , например, показать Продукт ‘s id и имя :
В этой статье мы рассмотрели, как проецировать свойства сущностей с помощью JPA и Hibernate.
Важно отметить, что Hibernate устарел свой API критериев начиная с версии 5.2 и далее в пользу API JPA CriteriaQuery . Но это только потому, что у команды Hibernate нет времени, чтобы синхронизировать два разных API, которые в значительной степени делают одно и то же.
И, конечно же, код, используемый в этой статье, можно найти на GitHub .