getSingleResult()导致NoResultException上的回滚

时间:2018-10-12 10:29:40

标签: hibernate jpa java-ee

我在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})(不知道它是否在容器管理的交易中起任何作用),但没有成功。

0 个答案:

没有答案