Автор оригинала: Priyesh Mashelkar.
1. Обзор
Основным недостатком того, что HQL и SQL разбросаны по объектам доступа к данным, является то, что это делает код нечитаемым. Следовательно, возможно, имеет смысл сгруппировать все HQL и SQL в одном месте и использовать только их ссылку в фактическом коде доступа к данным. К счастью, Hibernate позволяет нам делать это с именованными запросами.
Именованный запрос-это статически определенный запрос с предопределенной неизменяемой строкой запроса. Они проверяются при создании sessionfactory, что приводит к быстрому сбою приложения в случае ошибки.
В этой статье мы рассмотрим, как определить и использовать именованные запросы Hibernate с помощью @NamedQuery и @NamedNativeQuery аннотации.
2. Сущность
Давайте сначала рассмотрим сущность, которую мы будем использовать в этой статье:
@Entity public class DeptEmployee { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE) private long id; private String employeeNumber; private String designation; private String name; @ManyToOne private Department department; // getters and setters }
В нашем примере мы получим сотрудника на основе его номера сотрудника.
3. Именованный запрос
Чтобы определить это как именованный запрос, мы будем использовать org.hibernate.аннотации.NamedQuery аннотация. Это расширяет javax .persistence.NamedQuery с функциями гибернации.
Мы определим его как аннотацию класса Dept Employee :
@org.hibernate.annotations.NamedQuery(name = "DeptEmployee_findByEmployeeNumber", query = "from DeptEmployee where employeeNumber = :employeeNo")
Важно отметить, что каждая аннотация @NamedQuery прикреплена ровно к одному классу сущностей или сопоставленному суперклассу. Но, поскольку область именованных запросов-это вся единица сохранения, мы должны тщательно выбирать имя запроса, чтобы избежать столкновения. И мы добились этого, используя имя сущности в качестве префикса.
Если у нас есть более одного именованного запроса для сущности, мы будем использовать аннотацию @NamedQueries , чтобы сгруппировать их:
@org.hibernate.annotations.NamedQueries({ @org.hibernate.annotations.NamedQuery(name = "DeptEmployee_FindByEmployeeNumber", query = "from DeptEmployee where employeeNumber = :employeeNo"), @org.hibernate.annotations.NamedQuery(name = "DeptEmployee_FindAllByDesgination", query = "from DeptEmployee where designation = :designation"), @org.hibernate.annotations.NamedQuery(name = "DeptEmployee_UpdateEmployeeDepartment", query = "Update DeptEmployee set department = :newDepartment where employeeNumber = :employeeNo"), ... })
Обратите внимание, что запрос HQL может быть операцией в стиле DML. Таким образом, это не обязательно должен быть только оператор select . Например, у нас может быть запрос на обновление, как в Dept Employee_Update Обозначение сотрудника выше.
3.1. Настройка функций запросов
Мы можем задать различные функции запроса с помощью аннотации @NamedQuery . Давайте рассмотрим пример:
@org.hibernate.annotations.NamedQuery( name = "DeptEmployee_FindAllByDepartment", query = "from DeptEmployee where department = :department", timeout = 1, fetchSize = 10 )
Здесь мы настроили интервал ожидания и размер выборки. Помимо этих двух, мы также можем установить такие функции, как:
- кэшируемый – является ли запрос (результаты) кэшируемым или нет
- CacheMode – режим кэша, используемый для этого запроса; это может быть один из GET, IGNORE, NORMAL, PUT, или REFRESH
- cacheRegion – если результаты запроса можно кэшировать, назовите область кэша запросов для использования
- комментарий – комментарий, добавленный к сгенерированному SQL-запросу; предназначен для баз данных
- FlushMode – режим сброса для этого запроса, один из ALWAYS, AUTO, COMMIT, MANUAL, или PERSISTENCE_CONTEXT
3.2. Использование именованного запроса
Теперь, когда мы определили именованный запрос, давайте использовать его для получения сотрудника:
Queryquery = session.createNamedQuery("DeptEmployee_FindByEmployeeNumber", DeptEmployee.class); query.setParameter("employeeNo", "001"); DeptEmployee result = query.getSingleResult();
Здесь мы использовали метод createNamedQuery . Он принимает имя запроса и возвращает org.hibernate.запрос.Запрос объект.
4. Именованный Собственный запрос
Помимо запросов HQL, мы также можем определить собственный SQL как именованный запрос. Для этого мы можем использовать аннотацию @NamedNativeQuery . Хотя он похож на @NamedQuery , он требует немного большей конфигурации.
Давайте рассмотрим эту аннотацию на примере:
@org.hibernate.annotations.NamedNativeQueries( @org.hibernate.annotations.NamedNativeQuery(name = "DeptEmployee_GetEmployeeByName", query = "select * from deptemployee emp where name=:name", resultClass = DeptEmployee.class) )
Поскольку это собственный запрос, нам придется указать Hibernate, к какому классу сущностей сопоставлять результаты. Следовательно, мы использовали Класс результатов собственность для этого.
Другой способ отображения результатов – использовать Сопоставление результатов собственность. Здесь мы можем указать имя предопределенного SqlResultSetMapping .
Обратите внимание, что мы можем использовать только один из классов result и ResultSetMapping .
4.1. Использование именованного собственного запроса
Чтобы использовать именованный собственный запрос, мы можем использовать Session.createNamedQuery() :
Queryquery = session.createNamedQuery("DeptEmployee_FindByEmployeeName", DeptEmployee.class); query.setParameter("name", "John Wayne"); DeptEmployee result = query.getSingleResult();
Или Session.get NamedNativeQuery() :
NativeQuery query = session.getNamedNativeQuery("DeptEmployee_FindByEmployeeName"); query.setParameter("name", "John Wayne"); DeptEmployee result = (DeptEmployee) query.getSingleResult();
Единственное различие между этими двумя подходами заключается в типе возвращаемого значения. Второй подход возвращает Собственный запрос, который является подклассом Query .
5. Хранимые процедуры и функции
Мы также можем использовать аннотацию @NamedNativeQuery для определения вызовов хранимых процедур и функций:
@org.hibernate.annotations.NamedNativeQuery( name = "DeptEmployee_UpdateEmployeeDesignation", query = "call UPDATE_EMPLOYEE_DESIGNATION(:employeeNumber, :newDesignation)", resultClass = DeptEmployee.class)
Обратите внимание, что, хотя это запрос на обновление, мы использовали свойство result Class . Это связано с тем, что Hibernate не поддерживает чисто собственные скалярные запросы. И способ обойти эту проблему-либо установить класс result , либо сопоставление |/ResultSetMapping.
6. Заключение
В этой статье мы рассмотрели, как определить и использовать именованные HQL и собственные запросы.
Исходный код доступен на GitHub .