Механизм обработки CallableStatement
по умолчанию
При вызове метода execute
в JPA StoredProcedureQuery
или outputs().getCurrent()
в Hibernate ProcedureCall
Hibernate выполняет следующие действия:
Обратите внимание, что JDBC CallableStatement
подготовлен и сохранен в связанном объекте ProcedureOutputsImpl
. При вызове метода getOutputParameterValue
Hibernate будет использовать базовый CallableStatement
для извлечения параметра OUT
.
По этой причине базовый JDBC CallableStatement остается открытым даже после выполнения хранимой процедуры и извлечения параметров OUT или REF_CURSOR.
Теперь, по умолчанию, CallableStatement
закрывается после завершения текущей запущенной транзакции базы данных, либо посредством вызова commit
или rollback
.
Закрытие оператора JDBC как можно скорее
Поэтому, чтобы закрыть JDBC CallableStatement
как можно скорее, вы должны вызвать release
после извлечения всех данных, которые вы хотели получить из хранимой процедуры:
StoredProcedureQuery query = entityManager
.createStoredProcedureQuery("count_comments")
.registerStoredProcedureParameter(
"postId",
Long.class,
ParameterMode.IN
)
.registerStoredProcedureParameter(
"commentCount",
Long.class,
ParameterMode.OUT
)
.setParameter("postId", 1L);
try {
query.execute();
Long commentCount = (Long) query
.getOutputParameterValue("commentCount");
assertEquals(Long.valueOf(2), commentCount);
} finally {
query.unwrap(ProcedureOutputs.class).release();
}
Вызов метода release
для связанного объекта ProcedureOutputs
в блоке finally
обеспечивает закрытие JDBC CallableStatement
независимо от результата вызова хранимой процедуры.
Hibernate 6 года
Теперь вызов release
вручную немного утомителен, поэтому я решил создать проблему HHH-13215 Jira, которая, начиная с Hibernate ORM 6, позволяет переписать предыдущий пример, как этот :
Long commentCount = doInJPA(entityManager -> {
try(ProcedureCall query = entityManager
.createStoredProcedureQuery("count_comments")
.unwrap(ProcedureCall.class)) {
return (Long) query
.registerStoredProcedureParameter(
"postId",
Long.class,
ParameterMode.IN
)
.registerStoredProcedureParameter(
"commentCount",
Long.class,
ParameterMode.OUT
)
.setParameter("postId", 1L)
.getOutputParameterValue("commentCount");
}
});
Для получения более подробной информации, ознакомьтесь с этой статьей .