Я использую управляемые контейнером транзакции в приложении, запущенном на Wildfly 14.
Следующий код завершается ошибкой из-за непредвиденного отката транзакции:
@Transactional
public User example(...) {
User user = findUserByName(...);
// ...
}
private User findUserByName(String username) {
try {
User user = userDao.findUserByName(username); // throws NoResultException
// ...
return user;
} catch (NoResultException e) {
List<User> users = userDao.getAll(); // throws SQLException: Transaction cannot proceed: STATUS_MARKED_ROLLBACK
// ...
}
}
Чтение JavaDoc из NoResultException , в контракте четко указано:
Это исключение не приведет к тому, что текущая транзакция, если она активна, будет помечена для отката.
Тем не менее транзакция, по-видимому, откатывается, так как getAll()
(или любой другой запрос) выдает исключение со следующей основной причиной:
Caused by: javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: could not prepare statement
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:154)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:181)
at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1514)
at org.hibernate.query.Query.getResultList(Query.java:135)
at org.jboss.as.jpa.container.TypedQueryNonTxInvocationDetacher.getResultList(TypedQueryNonTxInvocationDetacher.java:58)
at com.example.UserDao.getAll(UserDao.java:74)
... 64 more
Caused by: org.hibernate.exception.GenericJDBCException: could not prepare statement
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:47)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:113)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:182)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl.prepareQueryStatement(StatementPreparerImpl.java:148)
at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1984)
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1914)
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1892)
at org.hibernate.loader.Loader.doQuery(Loader.java:937)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:340)
at org.hibernate.loader.Loader.doList(Loader.java:2689)
at org.hibernate.loader.Loader.doList(Loader.java:2672)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2506)
at org.hibernate.loader.Loader.list(Loader.java:2501)
at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:504)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:395)
at org.hibernate.engine.query.spi.HQLQueryPlan.performList(HQLQueryPlan.java:220)
at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1508)
at org.hibernate.query.internal.AbstractProducedQuery.doList(AbstractProducedQuery.java:1537)
at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1505)
... 107 more
Caused by: java.sql.SQLException: IJ031070: Transaction cannot proceed: STATUS_MARKED_ROLLBACK
at org.jboss.jca.adapters.jdbc.WrapperDataSource.checkTransactionActive(WrapperDataSource.java:248)
at org.jboss.jca.adapters.jdbc.WrappedConnection.checkTransactionActive(WrappedConnection.java:1933)
at org.jboss.jca.adapters.jdbc.WrappedConnection.checkStatus(WrappedConnection.java:1948)
at org.jboss.jca.adapters.jdbc.WrappedConnection.checkTransaction(WrappedConnection.java:1922)
at org.jboss.jca.adapters.jdbc.WrappedConnection.prepareStatement(WrappedConnection.java:452)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$5.doPrepare(StatementPreparerImpl.java:146)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:172)
userDao.findUserByName
просто выполняет следующее:
public User findUserByName(String username) {
return em.createNamedQuery("User.findByName", User.class)
.setParameter("name", username)
.getSingleResult();
}
Мне не хватает какой-то конфигурации?Я даже пытался @Transactional(dontRollbackOn = {NoResultException.class})
(не знаю, имеет ли это какое-то значение в транзакциях, управляемых контейнером), но безуспешно.