Листинг 6.27. Класс Customer_, описывающий метамодель Customer

@Generated("EclipseLink")

@StaticMetamodel(Customer.class)

public class Customer_ {

··public static volatile SingularAttribute id;

··public static volatile SingularAttribute firstName;

··public static volatile SingularAttribute lastName;

··public static volatile SingularAttribute age;

··public static volatile SingularAttribute email;

··public static volatile SingularAttribute address;

}

В классе статической метамодели каждый атрибут сущности Customer определяется подклассом javax.persistence.metamodel.Attribute (CollectionAttribute, ListAttribute, MapAttribute, SetAttribute или SingularAttribute). Каждый из этих атрибутов использует обобщения и является строго типизированным (например, SingularAttribute, age). В листинге 6.28 приведен точно такой же код, что и в листинге 6.25, но пересмотренный с использованием класса статической метамодели (c.get("age") превратилось в c.get(Customer_.age)). Еще одно преимущество безопасности типов заключается в том, что метамодель определяет атрибут age как имеющий тип Integer, поэтому нет необходимости преобразовывать его в Integer с помощью as(Integer.class).

Листинг 6.28. Типобезопасный запрос с использованием критериев, обеспечивающий выборку всех клиентов старше 40 лет

CriteriaBuilder builder = em.getCriteriaBuilder();

CriteriaQuery criteriaQuery = builder.createQuery(Customer.class);

Root c = criteriaQuery.from(Customer.class);

criteriaQuery.select(c). where(builder.greaterThan(c.get(Customer_.age), 40));

Query query = em.createQuery(criteriaQuery). getResultList();

List customers = query.getResultList();

Опять-таки это лишь примеры того, что вы можете сделать с помощью Criteria API. Это очень богатый API-интерфейс, который всесторонне охарактеризован в главах 5 и 6 спецификации JPA 2.1.

Примечание

Классы, используемые в случае со статической метамоделью, например Attribute или SingularAttribute, являются стандартными и определены в пакете javax.persistence.metamodel. Однако генерирование классов статической метамодели зависит от реализации. EclipseLink использует внутренний класс CanonicalModelProcessor. Этот класс может вызываться вашей интегрированной средой разработки, пока вы разрабатываете Java-команду, Ant-задание или Maven-плагин.

<p>«Родные» запросы</p>

JPQL обладает очень богатым синтаксисом, который позволяет обрабатывать сущности в любой форме и обеспечивает переносимость между базами данных. JPA дает возможность использовать специфические особенности баз данных благодаря «родным» запросам. «Родные» запросы принимают «родной» SQL-оператор (SELECT, UPDATE или DELETE) в качестве параметра и возвращают экземпляр Query для выполнения этого оператора. Однако нельзя рассчитывать на переносимость «родных» запросов между базами данных.

Если код не является переносимым, то почему бы не использовать JDBC-вызовы? Главная причина, в силу которой следует задействовать «родные» запросы JPA, состоит в том, что результат запроса будет автоматически преобразован обратно в сущности. Если вы захотите извлечь все экземпляры сущности Customer из базы данных с использованием SQL, то вам потребуется прибегнуть к методу EntityManager.createNativeQuery(), принимающему в качестве параметров SQL-запрос и класс-сущность, в который должен быть отображен результат.

Перейти на страницу:

Похожие книги