«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_ и будет выглядеть примерно так: ссылки на атрибуты. API запроса критериев предоставляет перегруженные методы, которые принимают ссылки на строки, а также реализации интерфейса атрибутов.

@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";
}

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

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

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

//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();

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

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

«

The source code of this tutorial can be found over on Github.