1. Обзор
Хранимые процедуры — это наборы скомпилированных операторов SQL, находящихся в базе данных. Они используются для инкапсуляции и совместного использования логики с другими программами, а также извлекают выгоду из функций, специфичных для базы данных, таких как подсказки индекса или определенные ключевые слова.
В этой статье показано, как использовать Hibernate для вызова хранимой процедуры в базе данных MySQL .
2. Хранимые процедуры в MySQL
Прежде чем мы обсудим, как вызвать хранимую процедуру из Hibernate, нам нужно ее создать.
Для этого быстрого примера MySQL мы создадим хранимую процедуру для получения всех записей из таблицы foo .
Чтобы создать хранимую процедуру, мы используем оператор CREATE PROCEDURE
:
DELIMITER //
CREATE PROCEDURE GetAllFoos()
LANGUAGE SQL
DETERMINISTIC
SQL SECURITY DEFINER
BEGIN
SELECT * FROM foo;
END //
DELIMITER;
Перед оператором BEGIN мы можем определить необязательные операторы.
Вы можете углубиться в детали этих утверждений, перейдя по ссылке официальной документации MySQL .
Мы можем использовать оператор CALL
, чтобы убедиться, что наша процедура ведет себя желаемым образом:
CALL GetAllFoos();
Теперь, когда наша хранимая процедура запущена и работает, давайте сразу перейдем к тому, как вызывать ее из Hibernate.
3. Вызовите хранимую процедуру с помощью Hibernate
Начиная с Hibernate 3, у нас есть возможность использовать необработанные операторы SQL, включая хранимые процедуры, для запросов к базе данных.
В этом разделе мы рассмотрим, казалось бы, простой пример, который продемонстрирует, как вызвать процедуру GetAllFoos()
с помощью Hibernate.
3.1. Конфигурация
Прежде чем мы начнем писать код, который может работать, нам нужно настроить Hibernate в нашем проекте.
И, конечно же, обо всем этом — зависимостях Maven, конфигурации MySQL, конфигурации Hibernate и создании экземпляров SessionFactory
— вы можете ознакомиться в статье Hibernate .
3.2. Вызов хранимой процедуры с помощью метода CreateNativeSQL
Hibernate позволяет напрямую выражать запросы в собственном формате SQL . Таким образом, мы можем напрямую создать собственный SQL-запрос и использовать оператор CALL для вызова хранимой процедуры
getAllFoos()
:
Query query = session.createSQLQuery("CALL GetAllFoos()").addEntity(Foo.class);
List<Foo> allFoos = query.list();
Приведенный выше запрос возвращает список, в котором каждый элемент является объектом Foo o
.
Мы используем метод addEntity()
для получения объектов сущностей из собственного SQL - запроса, в противном случае ClassCastException
будет генерироваться всякий раз, когда хранимая процедура возвращает не необработанное значение.
3.3. Вызов хранимой процедуры с помощью @NamedNativeQueries
Другой способ вызвать хранимую процедуру — использовать аннотацию @NamedNativeQueries
.
@NamedNativeQueries
используется для указания массива собственных именованных запросов SQL , относящихся к единице сохраняемости:
@NamedNativeQueries({
@NamedNativeQuery(
name = "callGetAllFoos",
query = "CALL GetAllFoos()",
resultClass = Foo.class)
})
@Entity
public class Foo implements Serializable {
// Model definition
}
Каждый именованный запрос, очевидно, имеет атрибут name , фактический SQL-запрос и resultClass
, который ссылается на сопоставленный объект Foo .
Query query = session.getNamedQuery("callGetAllFoos");
List<Foo> 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
:
@NamedStoredProcedureQuery(
name="GetFoosByName",
procedureName="GetFoosByName",
resultClasses = { Foo.class },
parameters={
@StoredProcedureParameter(name="fooName", type=String.class, mode=ParameterMode.IN)
}
)
Мы можем использовать метод setParameter()
для вызова нашей хранимой процедуры с параметром fooName
:
StoredProcedureQuery spQuery = entityManager.createNamedStoredProcedureQuery("GetFoosByName")
.setParameter("fooName", "NewFooName");
5. Вывод
В этой статье показано , как использовать Hibernate для вызова хранимой процедуры в базе данных MySQL с использованием различных подходов.
Стоит отметить, что не все СУБД поддерживают хранимые процедуры .
Вы можете ознакомиться с примерами, представленными в этой статье, в связанном проекте GitHub .