Перейти к основному содержимому

Критериальные запросы с использованием метамодели JPA

· 3 мин. чтения

1. Обзор

В этом руководстве мы обсудим, как использовать классы статической метамодели JPA при написании запросов критериев в Hibernate.

Нам потребуется базовое понимание API-интерфейсов запросов критериев в Hibernate, поэтому, если необходимо, ознакомьтесь с нашим руководством по запросам критериев для получения дополнительной информации по этой теме.

2. Почему метамодель JPA?

Часто, когда мы пишем критерий запроса, нам нужно ссылаться на классы сущностей и их атрибуты.

Теперь один из способов сделать это — указать имена атрибутов в виде строк. Но, это имеет несколько недостатков.

Во-первых, мы должны искать имена атрибутов сущности. И, если имя столбца будет изменено позже в жизненном цикле проекта, нам придется реорганизовать каждый запрос, в котором используется это имя.

Метамодель JPA была введена сообществом, чтобы избежать этих недостатков и обеспечить статический доступ к метаданным классов управляемых объектов.

3. Класс сущности

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

Во-первых, давайте посмотрим на наш класс Student :

@Entity
@Table(name = "students")
public class Student {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;

@Column(name = "first_name")
private String firstName;

@Column(name = "last_name")
private String lastName;

@Column(name = "grad_year")
private int gradYear;

// standard getters and setters
}

4. Генерация классов метамодели JPA

Затем нам нужно сгенерировать классы метамодели, и для этой цели мы будем использовать инструмент генератора метамодели, предоставляемый JBoss . JBoss — это лишь один из многих инструментов, доступных для создания метамодели. Другие подходящие инструменты включают EclipseLink , OpenJPA и DataNucleus .

Чтобы использовать инструмент JBoss, нам нужно добавить последнюю зависимость в наш файл pom.xml , и инструмент сгенерирует классы метамодели, как только мы вызовем команду сборки maven:

<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-jpamodelgen</artifactId>
<version>5.3.7.Final</version>
</dependency>

Обратите внимание: нам нужно добавить папку target/generated-classes в путь к классам нашей IDE , так как по умолчанию классы будут генерироваться только в этой папке.

5. Классы статической метамодели JPA

В соответствии со спецификацией JPA сгенерированный класс будет находиться в том же пакете, что и соответствующий класс сущности, и будет иметь то же имя с добавленным «» (подчеркивание) в конце. Итак, класс метамодели, сгенерированный для класса Student , будет `Student` и будет выглядеть примерно так:

@Generated(value = "org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor")
@StaticMetamodel(Student.class)
public abstract class Student_ {

public static volatile SingularAttribute<Student, String> firstName;
public static volatile SingularAttribute<Student, String> lastName;
public static volatile SingularAttribute<Student, Integer> id;
public static volatile SingularAttribute<Student, Integer> gradYear;

public static final String FIRST_NAME = "firstName";
public static final String LAST_NAME = "lastName";
public static final String ID = "id";
public static final String GRAD_YEAR = "gradYear";
}

6. Использование классов метамодели JPA

Мы можем использовать статические классы метамодели так же, как мы использовали бы ссылки String на атрибуты. API запроса критериев предоставляет перегруженные методы, которые принимают ссылки на строки , а также реализации интерфейса атрибутов .

Давайте посмотрим на запрос критериев, который выведет всех студентов , окончивших учебу в 2015 году:

//session set-up code
CriteriaBuilder cb = session.getCriteriaBuilder();
CriteriaQuery<Student> criteriaQuery = cb.createQuery(Student.class);

Root<Student> root = criteriaQuery.from(Student.class);
criteriaQuery.select(root).where(cb.equal(root.get(Student_.gradYear), 2015));

Query<Student> query = session.createQuery(criteriaQuery);
List<Student> results = query.getResultList();

Обратите внимание, как мы использовали ссылку Student_.gradYear вместо обычного имени столбца grad_year .

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

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

Исходный код этого руководства можно найти на Github .