Содержание
Criteria API предоставляет безопасный для типов способ программного определения запросов. Как и в JPQL, вы можете использовать его для выбора набора атрибутов сущности и сопоставления каждой записи набора результатов с простым старым Java-объектом (POJO).
Criteria API поддерживает тот же набор функций, что и JPQL, и я показываю в своей новой книге Hibernate Tips — более 70 решений общих проблем Hibernate, как вы можете использовать его для реализации различных вариантов использования. Это кулинарная книга Hibernate с более чем 70 готовыми рецептами для таких тем, как базовые и расширенные сопоставления, ведение журналов, поддержка Java 8, кэширование и статически и динамически определяемые запросы. Вы можете получить его на этой неделе на Amazon по специальной стартовой цене всего в $ 2,99.
Давайте посмотрим на один из рецептов, включенных в книгу. Он использует Criteria API для программного определения запроса, который выбирает набор столбцов базы данных и возвращает их как POJO. Чтобы получить максимальную отдачу от этого поста, вы уже должны быть знакомы с основными понятиями Hibernate .
Как выбрать POJO с помощью CriteriaQuery
проблема
JPQL поддерживает выражения конструктора для выбора POJO вместо сущностей или скалярных значений. Могу ли я сделать то же самое с Criteria API?
Решение
Вы можете использовать аналогичное выражение конструктора с Criteria API, как в JPQL-запросах. В следующем примере я хочу выбрать объекты AuthorValue
.
public class AuthorValue { private String firstName; private String lastName; public AuthorValue(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } ... }
Определение CriteriaQuery
следует тому же подходу, который используется для выбора объектов.
Сначала вам нужно получить экземпляр CriteriaBuilder
из EntityManager
. Это фабричный класс, который помогает вам определять различные части вашего запроса, такие как параметры связывания, вызовы функций и предикаты.
Затем вы создаете экземпляр CriteriaQuery
который является корнем графа объектов, представляющего ваш запрос. Я рекомендую createQuery
тип возврата вашего запроса в качестве параметра метода createQuery
. Он создает типизированный экземпляр интерфейса CriteriaQuery
. Я хочу выбрать объекты AuthorValue
в этом примере и, следовательно, предоставить AuthorValue.class
в качестве параметра.
На следующем шаге вы определяете предложение FROM
запроса. В этом примере я использую сущность Author
в качестве корня запроса.
Затем вы можете определить проекцию вашего запроса. В этом примере это вызов конструктора AuthorValue
. Метод construct
CriteriaBuilder
позволяет вам определять вызовы конструктора. Вызовите этот метод, используя класс, который Hibernate создает в качестве первого параметра, и необязательный список Selections
, которые используются в качестве параметров конструктора.
В этом примере я использую класс метамодели JPA Author_
для ссылки на атрибуты firstName
и lastName
объекта Author
. Если вы не знакомы с метамоделью JPA, взгляните на совет Hibernate Как ссылаться на атрибуты сущностей безопасным для типов способом, который обеспечивает удобный и безопасный для ссылок способ ссылаться на атрибуты сущностей.
Определение WHERE
является необязательным. Если вы хотите выбрать все записи из базы данных, вы можете пропустить этот блок и выполнить свой запрос. Вот что я делаю в этом примере. Вы можете увидеть пример определения WHERE
в разделе Как выбрать объекты с главой CriteriaQuery.
CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<AuthorValue> q = cb.createQuery(AuthorValue.class); Root<Author> root = q.from(Author.class); q.select( cb.construct( AuthorValue.class, root.get(Author_.firstName), root.get(Author_.lastName)));
Это все, что вам нужно сделать, чтобы определить CriteriaQuery
. Теперь вы можете выполнить его в два этапа. Сначала вам нужно вызвать метод createQuery
EntityManager
с вашим CriteriaQuery
. Этот вызов метода возвращает тот же интерфейс TypedQuery
который используется в ваших запросах JPQL. Вы можете использовать его, чтобы установить значения параметров привязки или разбить результат запроса на страницы. Я не использую никаких параметров привязки в этом примере и, следовательно, могу пропустить эту часть. На последнем этапе вам нужно вызвать метод TypedQuery
интерфейсе TypedQuery
чтобы выполнить запрос и получить List
объектов AuthorValue
.
TypedQuery<AuthorValue> query = em.createQuery(q); List<AuthorValue> authors = query.getResultList();
Когда я создал запрос, я ссылался на атрибуты firstName
и lastName
в определении вызова конструктора. Как видно из следующих сообщений журнала, Hibernate использовал эти ссылки для создания запроса SQL, который выбирает столбцы firstName
и lastName
из таблицы Author
.
13:43:09,884 DEBUG [org.hibernate.SQL] - select author0_.firstName as col_0_0_, author0_.lastName as col_1_0_ from Author author0_
Исходный код
Вы можете найти ссылку на скачивание проекта с исполняемыми тестовыми примерами для этой подсказки Hibernate в книге .
Учить больше
Если вы не хотите создавать POJO для представления результата запроса, вы также можете выбрать набор скалярных значений . Я покажу вам, как это сделать, в главе Как выбрать несколько скалярных значений в CriteriaQuery .
И если вы хотите использовать Criteria API в своем проекте, вы также должны взглянуть на метамодель JPA . Он предоставляет отличный способ создания запросов безопасным для типов способом. Я покажу вам, как использовать и генерировать необходимые классы в главе Как ссылаться на атрибуты сущности безопасным для типов способом .
Резюме
API Criteria предоставляет безопасную опцию для программного определения запросов. Как вы видели в отрывке из книги, вы можете использовать его, чтобы выбрать набор столбцов базы данных и позволить Hibernate сопоставить каждую запись набора результатов с POJO.
Получить больше рецептов, как это в моей новой книге Hibernate Советы: более 70 решений общих проблем Hibernate . Он дает вам более 70 готовых рецептов для таких тем, как базовые и расширенные отображения, ведение журналов, поддержка Java 8, кэширование и статически и динамически определяемые запросы. Всего за несколько дней вы можете получить электронную книгу за 2,99 долларов и мягкую обложку за 12,99 долларов .