Ошибка Quarkus и JDBC при попытке зафиксировать транзакцию
Я экспериментирую с Quarkus, создавая небольшое REST-приложение. Для этого я решил использовать источник данных Agroal, но не Panache или простой Hibernate (как показано в их примерах), а я использую JDBC.
Для взаимодействия с базой данных я создал небольшую службу, которая вводит AgroalDataSource и использует его для открытия соединений с базой данных. Указанная служба предоставляет два метода: один для выполнения транзакционных запросов, а второй - транзакционных. Для первой части все работает нормально, но когда я пытаюсь обновить запись в базе данных, действие завершается ошибкой при попытке зафиксировать соединение.
public <E> E update(TransactionalRunner<E> runner) {
try (var connection = dataSource.getConnection()) {
return attemptTransactional(runner, connection);
} catch (SQLException e) {
log.error("Establishing a database connection has failed", e);
throw new DataAccessException(e);
}
}
private <E> E attemptTransactional(TransactionalRunner<E> runner, Connection connection) {
try {
connection.setAutoCommit(Boolean.FALSE);
E result = runner.run(new QueryRunner(), connection);
connection.commit();
return result;
} catch (SQLException e) {
try {
log.error("Committing a transaction has failed. Attempting rollback", e);
DbUtils.rollback(connection);
throw new DataAccessException(e);
} catch (SQLException ex) {
log.error("Rolling back a transaction has failed. Giving up...", ex);
throw new DataAccessException(ex);
}
}
}
Я получаю следующую трассировку стека:
2019-12-21 14:25:59,350 ERROR [com.ari.rev.dat.DatabaseAccessService] (vert.x-worker-thread-1) Committing a transaction has failed. Attempting rollback: java.sql.SQLException: Attempting to commit while taking part in a transaction
at io.agroal.pool.wrapper.ConnectionWrapper.commit(ConnectionWrapper.java:183)
at com.ariskourt.revolut.database.DatabaseAccessService.attemptTransactional(DatabaseAccessService.java:44)
at com.ariskourt.revolut.database.DatabaseAccessService.update(DatabaseAccessService.java:33)
at com.ariskourt.revolut.database.DatabaseAccessService_ClientProxy.update(DatabaseAccessService_ClientProxy.zig:114)
at com.ariskourt.revolut.services.AccountTransferService.transferAmount(AccountTransferService.java:66)
at com.ariskourt.revolut.services.AccountTransferService_Subclass.transferAmount$$superaccessor2(AccountTransferService_Subclass.zig:164)
at com.ariskourt.revolut.services.AccountTransferService_Subclass$$function$$2.apply(AccountTransferService_Subclass$$function$$2.zig:51)
at io.quarkus.arc.impl.AroundInvokeInvocationContext.proceed(AroundInvokeInvocationContext.java:54)
at io.quarkus.narayana.jta.runtime.interceptor.TransactionalInterceptorBase.invokeInOurTx(TransactionalInterceptorBase.java:119)
at io.quarkus.narayana.jta.runtime.interceptor.TransactionalInterceptorBase.invokeInOurTx(TransactionalInterceptorBase.java:92)
at io.quarkus.narayana.jta.runtime.interceptor.TransactionalInterceptorRequired.doIntercept(TransactionalInterceptorRequired.java:32)
at io.quarkus.narayana.jta.runtime.interceptor.TransactionalInterceptorBase.intercept(TransactionalInterceptorBase.java:53)
at io.quarkus.narayana.jta.runtime.interceptor.TransactionalInterceptorRequired.intercept(TransactionalInterceptorRequired.java:26)
at io.quarkus.narayana.jta.runtime.interceptor.TransactionalInterceptorRequired_Bean.intercept(TransactionalInterceptorRequired_Bean.zig:168)
at io.quarkus.arc.impl.InterceptorInvocation.invoke(InterceptorInvocation.java:41)
at io.quarkus.arc.impl.AroundInvokeInvocationContext.perform(AroundInvokeInvocationContext.java:41)
at io.quarkus.arc.impl.InvocationContexts.performAroundInvoke(InvocationContexts.java:32)
Я использую источник данных Agroal по умолчанию, предлагаемый Quarkus, без какой-либо специальной конфигурации. ДляQueryRunner
это всего лишь часть пакета Apache DbUtils.
Кто-нибудь знает, как это решить?