Есть ограничение: областью видимости для имени запроса является та, что имеет место в случае с единицей сохраняемости. При этом имя должно быть уникальным в этой области видимости, то есть может присутствовать только один метод findAll. Запрос findAll, который касается клиентов, и запрос findAll, касающийся адресов, должны именоваться по-разному. Общепринятая практика — снабжение имени запроса префиксом в виде имени сущности. Например, запрос findAll к сущности Customer имел бы имя Customer.findAll.
Другая проблема заключается в том, что имя запроса, являющееся строкой, подвергается манипуляциям, и, если вы допустите опечатку или выполните реорганизацию своего кода, то могут быть сгенерированы исключения, говорящие о том, что запрос не существует. Чтобы ограничить риски, вы можете заменить имя запроса константой. В листинге 6.23 показано, как произвести реорганизацию сущности Customer.
@Entity
@NamedQuery(name = Customer.FIND_ALL, query="select c from Customer c"),
public class Customer {
··public static final String FIND_ALL = "Customer.findAll";
··// Атрибуты, конструкторы, геттеры, сеттеры
}
Константа FIND_ALL однозначно идентифицирует запрос findAll путем снабжения его имени префиксом в виде имени сущности. Та же константа затем используется в аннотации @NamedQuery, и вы можете задействовать ее для выполнения запроса, как показано далее:
TypedQuery
······Customer.class);
Criteria API (или объектно-ориентированные запросы)
До сих пор при написании JPQL-операторов (для выполнения динамических или именованных запросов) я использовал строки. Такой подход удобен тем, что позволяет писать краткие запросы к базам данных. Однако он обладает и недостатками, к которым относятся предрасположенность к ошибкам и сложность манипулирования с помощью внешнего фреймворка. Это строка, а в результате вы прибегаете к конкатенации строк, из-за чего можете допустить множество опечаток. Например, вы можете допустить опечатки в ключевых словах JPQL (SLECT вместо SELECT), именах классов (Custmer вместо Customer) или атрибутов (firstname вместо firstName). Вы также можете написать синтаксически неправильный оператор (SELECT c WHERE c.firstName = 'John' FROM Customer). Любая из этих ошибок будет обнаружена во время выполнения, а иногда может быть сложно выяснить, откуда происходит определенный дефект.
С выходом JPA 2.0 появился новый API-интерфейс под названием
SELECT c FROM Customer c WHERE c.firstName = 'Винсент'
Этот JPQL-оператор был переписан в листинге 6.24 объектно-ориентированным образом с использованием Criteria API.
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery
Root
criteriaQuery.select(c). where(builder.equal(c.get("firstName"), "Винсент"));
Query query = em.createQuery(criteriaQuery). getResultList();
List