Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
2013_1 / КСТ / Разработка веб-приложений.pdf
Скачиваний:
160
Добавлен:
23.02.2015
Размер:
2.74 Mб
Скачать

14. Язык запросов Criteria API

Описание языка запросов Criteria API приведено в части 25 учебника [1].

Подобно языку JPQL, язык Criteria API основывается на абстрактной схеме хранимых сущностей, их отношений и вложенных объектах. Это позволяет разработчикам нахо-

дить, модифицировать и удалять сущности, вызывая операторы Java Persistence API.

Эти языки внутренне связаны и выполняют подобные операции.

Простой пример запроса Criteria Query возвращает экземпляры сущности Pet в

наборе данных:

EntityManager em = ...;

CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<Pet> cq = cb.createQuery(Pet.class); Root<Pet> pet = cq.from(Pet.class); cq.select(pet);

TypeQuery<Pet> q = em.createQuery(cq); List<Pet> allPets = q.getResultList();

Эквивалентный запрос JPQL:

SELECT p FROM Pet p

Пример демонстрирует основные шаги в создании запроса Criteria:

использование экземпляра EntityManager для создания объекта

CriteriaBuilder;

создание объекта запроса с использованием интерфейса CriteriaQuery. Атрибуты этого запроса будут модифицироваться деталями запроса;

установка корня запроса вызовом метода объекта CriteriaQuery;

задание типа результата запроса после вызова метода select объекта

CriteriaQuery;

подготовка запроса для исполнения путём создания экземпляра объекта класса TypedQuery<T> заданного типа результата;

исполнение запроса путем вызова метода getResultList объекта TypedQuery<T>. Так как запрос возвращает коллекцию сущностей, результат

имеет тип List.

14.1.Моделирование сущностей

сиспользованием Metamodel API

Metamodel API используется для создания метамодели управления сущностями

в заданном модуле хранилища. Для каждого класса сущности создается класс мета-

модели с подчеркиванием на конце имени и с атрибутами, соответствующими полям или свойствам класса сущности.

В следующем примере класс com.example.Pet имеет четыре хранимых поля: id, name, color и owners:

package com.example;

...

@Entity

public class Pet { @Id

173

protected Long id; protected String name; protected String color; @ManyToOne

protected Set<Person> owners;

...

}

Соответствующий класс метамодели:

package com.example;

...

@Static Metamodel(Pet.class) public class Pet_ {

public static volatile SingularAttribute<Pet, Long> id; public static volatile SingularAttribute<Pet, String> name; public static volatile SingularAttribute<Pet, String> color; public static volatile SetAttribute<Pet, Person> owners;

}

Классы метамодели, соответствующие сущностным классам, имеют тип javax. persistence.metamodel.EntityType<T> и обычно генерируются процессом аннотации или получаются вызовом метода getModel объекта корня запроса либо экземпляром класса Metamodel и затем передаются типу сущности методом entity.

Следующий пример получает динамически класс метамодели использованием метода Root<T>.getModel.

EntityManager em = ...;

CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery cq = cb.createQuery(Pet.class); Root<Pet> pet = cq.from(Pet.class); EntityType<Pet> Pet_ = pet.getModel();

Приведённый ниже пример получает динамически класс метамодели использо-

ванием метода Metamodel.getMetamodel. Затем вызывается метод entity метамодели.

EntityManager em = ...; Metamodel m = em.getMetamodel();

EntityType<Pet> Pet_ = m.entity(Pet.class);

14.2.Основы типизации запросов

вCriteria API и Metamodel API

Базовый набор запросов содержит опции select, from, where, как и в запросах

JPQL.

Интерфейс javax.persistence.criteria.CriteriaBuilder используется для создания:

запросов — Criteria queries;

выбора — selections;

выражений — expressions;

предикатов — predicates;

сортировки — ordering.

174

Для получения экземпляра интерфейса CriteriaBuilder вызовите метод getCriteriaBuilder для экземпляра EntityManager или EntityManagerFactory. Например:

EntityManager em = ...;

CriteriaBuilder cb = em.getCriteriaBuilder();

Запросы создаются интерфейсом javax.persistence.criteria.CriteriaQuery. Объект

CriteriaQuery определяет навигацию через одну или более сущностей. Он создается

методом CrtieriaBuilder.createQuery. Например:

CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);

Тип результата определяется параметром метода. Например, для типа String:

CriteriaQuery<String> cq = cb.createQuery(String.class);

14.3. Корни запроса

Для запросов CriteriaQuery корневая сущность запроса, от которой начинается

навигация, называется query root — корнем запроса. Создается корень вызовом ме-

тода from экземпляра CriteriaQuery. Аргумент для метода from — класс сущности или

экземпляр EntityType<T> для сущности, например, для класса:

CriteriaQuery<Pet> cq = cb.createQuery(Pet.class); Root<Pet> pet = cq.from(Pet.class);

Пример для экземпляра EntityType<T>:

EntityManager em = ...; Metamodel m = em.getMetamodel();

EntityType<Pet> Pet_ = m.entity(Pet.class); Root<Pet> pet = cq.from(Pet_);

Запрос может иметь несколько корней, например:

CriteriaQuery<Pet> cq = cb.createQuery(Pet.class); Root<Pet> pet1 = cq.from(Pet.class);

Root<Pet> pet2 = cq.from(Pet.class);

14.4.Использование объединения в запросе

Для запросов с навигацией по классам сущностей нужно определить объеди-

нение сущностей, вызвав один из методов From.join на объекте корня запроса или

другом объединяемом объекте. Метод join аналогичен ключевому слову JOIN в JPQL.

Цель метода заключается в использовании класса метамодели типа EntityType<T> для задания хранимого поля или свойства объединения сущностей. Метод join возвра-

щает объект типа Join<X, Y>, где X есть исходная сущность, а Y — целевая сущность

объединения. Пример запроса с объединением:

CriteriaQuery<Pet> cq = cb.createQuery(Pet.class); Metamodel m = em.getMetamodel();

EntityType<Pet> Pet_ = m.entity(Pet.class); Root<Pet> pet = cq.from(Pet.class);

Join<Pet, Owner> owner = pet.join(Pet_.owners);

175

Объединения могут быть сцеплены совместно для навигации связанных сущностей без создания экземпляра Join<X, Y> для каждого объединения. Например:

CriteriaQuery<Pet> cq = cb.createQuery(Pet.class); Metamodel m = em.getMetamodel();

EntityType<Pet> Pet_ = m.entity(Pet.class); EntityType<Owner> Owner_ = m.entity(Owner.class);

Root<Pet> pet = cq.from(Pet.class); Join<Owner, Address> address = cq.join(Pet_.owners).join(Owner_.addresses);

14.5. Навигация путей в запросах

Объекты Path используются в опциях запросов select и where и могут быть

сущностями, объединениями сущностей или другими объектами Path. Метод Path.get используется для навигации атрибутов сущностей запроса. Аргумент ме-

тода get соответствует атрибуту сущности класса метамодели. Атрибут может быть

как с одним значением (@SingularAttribute в классе метамодели), так и коллекцией

(@CollectionAttribute, @SetAttribute, @ListAttribute или @MapAttribute ).

Пример использования объекта Path в опции select запроса:

CriteriaQuery<String> cq = cb.createQuery(String.class); Metamodel m = em.getMetamodel();

EntityType<Pet> Pet_ = m.entity(Pet.class); Root<Pet> pet = cq.from(Pet.class); cq.select(pet.get(Pet_.name));

Этот запрос возвращает имена всех любимцев в базе данных. Метод get вызывается для корня запроса pet с именем атрибута класса метамодели Pet_ как аргумент.

14.6. Ограничения на результаты запроса

Метод CriteriaQuery.where позволяет задавать ограничения на результат испол-

нения запроса аналогично ключу WHERE в запросе JPQL. Метод where производит оценку экземпляров интерфейса Expression для отбора результатов согласно условному выражению. Выражение создается методами, определёнными в интерфейсе

Expression и CriteriaBuilder.

14.6.1. Методы интерфейса Expression

Объекты Expression используются в опциях запроса select, where или having.

Методы условных выражений следующие:

isNull — проверка на значение null;

isNotNull — проверка на значение не null;

in — проверка на вхождение в список или коллекцию.

Пример использования выражения для поиска всех объектов с атрибутом color, равным null:

CriteriaQuery<Pet> cq = cb.createQuery(Pet.class); Metamodel m = em.getMetamodel();

EntityType<Pet> Pet_ = m.entity(Pet.class);

176

Root<Pet> pet = cq.from(Pet.class); cq.where(pet.get(Pet_.color).isNull());

Пример использования проверки in:

CriteriaQuery<Pet> cq = cb.createQuery(Pet.class); Metamodel m = em.getMetamodel();

EntityType<Pet> Pet_ = m.entity(Pet.class); Root<Pet> pet = cq.from(Pet.class); cq.where(pet.get(Pet_.color).in("brown", "black");

14.6.2. Методы интерфейса CriteriaBuilder

Интерфейс CriteriaBuilder задаёт дополнительные методы для создания выра-

жений, соответствующие операциям с арифметическими, строковыми данными, дан-

ными времени, даты и операциям выбора и функциям.

Операциями интерфейса CriteriaBuilder являются:

equal — равенство;

notEqual — неравенство;

gt — больше;

ge — больше или равно;

lt — меньше;

le — меньше или равно;

between — принадлежность интервалу;

like — проверка шаблоном.

Примеры использования методов CriteriaBuilder:

CriteriaQuery<Pet> cq = cb.createQuery(Pet.class); Metamodel m = em.getMetamodel();

EntityType<Pet> Pet_ = m.entity(Pet.class); Root<Pet> pet = cq.from(Pet.class);

cq.where(cb.equal(pet.get(Pet_.name)), "Fido");

...

CriteriaQuery<Pet> cq = cb.createQuery(Pet.class); Metamodel m = em.getMetamodel();

EntityType<Pet> Pet_ = m.entity(Pet.class); Root<Pet> pet = cq.from(Pet.class);

Date someDate = new Date(...); cq.where(cb.gt(pet.get(Pet_.birthday)), date);

CriteriaQuery<Pet> cq = cb.createQuery(Pet.class); Metamodel m = em.getMetamodel();

EntityType<Pet> Pet_ = m.entity(Pet.class); Root<Pet> pet = cq.from(Pet.class);

Date firstDate = new Date(...); Date secondDate = new Date(...);

cq.where(cb.between(pet.get(Pet_.birthday)), firstDate, secondDate);

177

Соседние файлы в папке КСТ