Хранимые процедуры в Hibernate

Хранимые процедуры с Hibernate

1. обзор

Хранимые процедуры - это наборы скомпилированных операторов SQLresiding in the database.. Они используются для инкапсуляции и совместного использования логики с другими программами, а также извлекают выгоду из специфичных для базы данных функций, таких как подсказки индекса или определенные ключевые слова.

В этой статье показано, как использоватьHibernate для вызоваstored procedure вMySQL database.

2. Хранимые процедуры в MySQL

Прежде чем мы обсудим, как вызвать хранимую процедуру из Hibernate, нам нужно ее создать.

В этом быстром примере MySQL мы используемcreate a stored procedure, чтобы получить все записи из таблицыfoo.

Чтобы создать хранимую процедуру, мы используем операторCREATE PROCEDURE:

DELIMITER //
    CREATE PROCEDURE GetAllFoos()
        LANGUAGE SQL
        DETERMINISTIC
        SQL SECURITY DEFINER
        BEGIN
            SELECT * FROM foo;
        END //
DELIMITER;

Перед операторомBEGIN мы можем определить необязательные операторы. Вы можете более детально изучить эти заявления, перейдя по официальной ссылкеMySQL documentation.

Мы можем использовать операторCALL, чтобы убедиться, что наша процедура ведет себя желаемым образом:

CALL GetAllFoos();

Теперь, когда у нас есть хранимая процедура, давайте перейдем к ее вызову из Hibernate.

3. Вызов хранимой процедуры в гибернации

Начиная с Hibernate 3, у нас есть возможность использовать необработанные операторы SQL, включая хранимые процедуры, для запроса к базе данных.

В этом разделе мы рассмотрим, казалось бы, простой пример, который покажет, как вызвать процедуруGetAllFoos() с помощью Hibernate.

3.1. конфигурация

Прежде чем мы начнем писать код, который можно запустить, нам нужно настроить Hibernate в нашем проекте.

И, конечно же, для всего этого - зависимости Maven, конфигурация MySQL, конфигурация Hibernate и создание экземпляраSessionFactory - вы можете проверитьHibernate article.

3.2. Вызов хранимой процедуры с использованием методаCreateNativeSQL

Hibernate позволяет напрямую выражать запросы в форматеnative SQL. Следовательно, мы можем напрямую создать собственный SQL-запрос и использовать операторCALL для вызова хранимой процедурыgetAllFoos():

Query query = session.createSQLQuery("CALL GetAllFoos()").addEntity(Foo.class);
List allFoos = query.list();

Вышеупомянутый запрос возвращает список, в котором каждый элемент является sbjectFoo o.

Мы используем методaddEntity() для получения объектов сущностей из собственного запросаSQL, в противном случаеClassCastException будет выдаваться всякий раз, когда хранимая процедура возвращает необработанное значение.

3.3. Вызов хранимой процедуры с использованием@NamedNativeQueries

Другой способ вызвать хранимую процедуру - использовать аннотацию@NamedNativeQueries.

@NamedNativeQueries используется для указания массива собственных именованных запросовSQLscoped to the persistence unit:

@NamedNativeQueries({
  @NamedNativeQuery(
    name = "callGetAllFoos",
    query = "CALL GetAllFoos()",
    resultClass = Foo.class)
})
@Entity
public class Foo implements Serializable {
    // Model definition
}

Каждый именованный запрос, очевидно, имеет атрибутname, фактическийSQL query иresultClass, который относится к отображаемому объектуFoo.

Query query = session.getNamedQuery("callGetAllFoos");
List allFoos = query.list();

АтрибутresultClass играет ту же роль, что и методaddEntity() в нашем предыдущем примере.

Оба этих подхода могут использоваться взаимозаменяемо, поскольку между ними нет реальных различий в отношении производительности или производительности.

3.4. Вызов хранимой процедуры с использованием@NamedStoredProcedureQuery

Если вы используетеJPA 2.1 иHibernate реализациюEntityManagerFactory иEntityManager.

Аннотацию@NamedStoredProcedureQuery можно использовать для объявления хранимой процедуры:

@NamedStoredProcedureQuery(
  name="GetAllFoos",
  procedureName="GetAllFoos",
  resultClasses = { Foo.class }
)
@Entity
public class Foo implements Serializable {
    // Model Definition
}

Чтобы вызвать наш запрос именованной хранимой процедуры, нам нужно создать экземплярEntityManager,, а затем вызвать методcreateNamedStoredProcedureQuery() для создания процедуры:

StoredProcedureQuery spQuery =
  entityManager.createNamedStoredProcedureQuery("getAllFoos");

Мы можем напрямую получить список сущностейFoo, вызвав методexecute() для объектаStoredProcedureQuery.

4. Хранимые процедуры с параметрами

Почти все наши хранимые процедуры требуют параметров. В этом разделе мы собираемся показать, как вызвать хранимую процедуру с параметрами изHibernate.

Давайте создадим хранимую процедуруgetFoosByName() вMySQL.

Эта процедура возвращает список объектовFoo, в которых атрибут name соответствует параметруfooName:

DELIMITER //
    CREATE PROCEDURE GetFoosByName(IN fooName VARCHAR(255))
        LANGUAGE SQL
        DETERMINISTIC
        SQL SECURITY DEFINER
        BEGIN
            SELECT * FROM foo WHERE name = fooName;
        END //
DELIMITER;

Для вызова процедурыGetFoosByName() мы будем использовать именованные параметры:

Query query = session.createSQLQuery("CALL GetFoosByName(:fooName)")
  .addEntity(Foo.class)
  .setParameter("fooName","New Foo");

Точно так же именованный параметр:fooName можно использовать с аннотацией@NamedNativeQuery:

@NamedNativeQuery(
  name = "callGetFoosByName",
  query = "CALL GetFoosByName(:fooName)",
  resultClass = Foo.class
)

Именованный запрос будет вызываться следующим образом:

Query query = session.getNamedQuery("callGetFoosByName")
  .setParameter("fooName","New Foo");

При использовании аннотации@NamedStoredProcedureQuery мы можем указать параметры с помощью@StoredProcedureParameter annotation:

@NamedStoredProcedureQuery(
  name="GetFoosByName",
  procedureName="GetFoosByName",
  resultClasses = { Foo.class },
  parameters={
    @StoredProcedureParameter(name="fooName", type=String.class, mode=ParameterMode.IN)
  }
)

Мы можем использовать методregisterStoredProcedureParameter() для вызова нашей хранимой процедуры с параметромfooName:

StoredProcedureQuery spQuery = entityManager.
  createNamedStoredProcedureQuery("GetFoosByName")
  .registerStoredProcedureParameter(
    "New Foo",
    String.class ,
    ParameterMode.IN
  );

5. Заключение

Эта статья продемонстрировалаhow to use Hibernate to call a stored procedure in a MySQL database с использованием разных подходов.

Стоит отметить, чтоnot all RDBMS support stored procedures.

Вы можете проверить примеры, представленные в этой статье, в связанномGitHub project.