Изменить переменные сеанса Oracle вне транзакции Hibernate

Мы уже давно используем подобный шаблон, чтобы обеспечить выполнение определенной операции с помощью BATCH NOWAIT из соображений производительности.

try {
    session.createSQLQuery("ALTER SESSION SET COMMIT_LOGGING='BATCH' COMMIT_WAIT='NOWAIT'").executeUpdate();
    // Do the operation (which also calls transaction.commit())
    return callback.apply(session);
} finally {
    session.createSQLQuery("ALTER SESSION SET COMMIT_LOGGING='IMMEDIATE' COMMIT_WAIT='WAIT'").executeUpdate();
}

Это отлично работало в Hibernate 4. Что касается Hibernate 5, последний оператор терпит неудачу, потому что он не находится внутри транзакции (поскольку он только что был зафиксирован).

javax.persistence.TransactionRequiredException: выполнение запроса на обновление/удаление

Это не обновление и не удаление, но executeUpdate() — единственный метод, который вы можете вызвать для выполнения этого оператора без возврата каких-либо строк. Это не должно быть в транзакции, поскольку переменные сеанса применяются ко всему соединению, и его необходимо выполнить для восстановления переменных сеанса, поскольку используется пул соединений.

Вместо этого я попытался использовать один из методов запроса, но в этом операторе есть строки -1, и он не позволяет мне складывать SELECT 1 FROM DUAL в конце.

Есть ли способ выполнить собственный запрос из Hibernate, который не обновляет/удаляет и не возвращает результаты вне транзакции?


person Nick    schedule 12.02.2019    source источник
comment
Спасибо, Ник. Вместо этого вы упомянули, что пытаетесь использовать методы запроса. Я стесняюсь спросить, но удовлетворит ли это ваше требование выполнить нечистый запрос, который изменил сеанс как побочный эффект?   -  person alexgibbs    schedule 12.02.2019


Ответы (1)


Использование базового Connection напрямую обходит проверки Hibernate и позволяет мне спокойно выполнить такой оператор.

try {
    session.doWork(conn ->
            conn.createStatement().execute("ALTER SESSION SET COMMIT_LOGGING='BATCH' COMMIT_WAIT='NOWAIT'")
    );
    return callback.apply(session);
} finally {
    session.doWork(conn ->
            conn.createStatement().execute("ALTER SESSION SET COMMIT_LOGGING='IMMEDIATE' COMMIT_WAIT='WAIT'")
    );
}
person Nick    schedule 12.02.2019