我在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
// ...
}
}
阅读NoResultException的JavaDoc,该合同明确规定:
此异常不会导致当前事务(如果正在进行)被标记为回滚。
显然,由于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})
(不知道它是否在容器管理的交易中起任何作用),但没有成功。