Рубрики
Без рубрики

Именованный запрос Hibernate

Узнайте, как определять и использовать именованные запросы HQL и собственные запросы.

Автор оригинала: 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. Использование именованного запроса

Теперь, когда мы определили именованный запрос, давайте использовать его для получения сотрудника:

Query query = 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() :

Query query = 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 .