当前位置: 首页 > 知识库问答 >
问题:

Spring Boot+Atomikos:try-catch中事务性JMS侦听器中引发的异常会立即导致回滚

梁鸿风
2023-03-14
@Transactional
public void handleMessage(UnmarshalledMessage message) {
    try {
        Thing thing = repository.find(message.getId());
        ...
    }
    catch (Exception e) {
        // NoResultException translated into EmptyResultDataAccessException
        logger.logUsingTransactions(e.getMessage());
        throw e;
    }
}
c.atomikos.jdbc.AtomikosSQLException - Transaction is marked for rollback only or has timed out
com.atomikos.datasource.xa.session.InvalidSessionHandleStateException: Transaction is marked for rollback only or has timed out
    at com.atomikos.datasource.xa.session.NotInBranchStateHandler.checkEnlistBeforeUse(NotInBranchStateHandler.java:39)
    at com.atomikos.datasource.xa.session.TransactionContext.checkEnlistBeforeUse(TransactionContext.java:70)
    at com.atomikos.datasource.xa.session.SessionHandleState.notifyBeforeUse(SessionHandleState.java:160)
    at com.atomikos.jdbc.AtomikosConnectionProxy.enlist(AtomikosConnectionProxy.java:207)
    at com.atomikos.jdbc.AtomikosConnectionProxy.invoke(AtomikosConnectionProxy.java:122)
    at com.sun.proxy.$Proxy129.prepareStatement(Unknown Source)
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.prepareStatement(DatabaseAccessor.java:1565)
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.prepareStatement(DatabaseAccessor.java:1514)
    at org.eclipse.persistence.internal.databaseaccess.DatabaseCall.prepareStatement(DatabaseCall.java:778)
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:621)
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:560)
    at org.eclipse.persistence.internal.sessions.AbstractSession.basicExecuteCall(AbstractSession.java:2055)
    at org.eclipse.persistence.sessions.server.ServerSession.executeCall(ServerSession.java:570)
    at org.eclipse.persistence.sessions.server.ClientSession.executeCall(ClientSession.java:258)
    at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:242)
    at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:228)
    at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.selectOneRow(DatasourceCallQueryMechanism.java:714)
    at org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.selectOneRowFromTable(ExpressionQueryMechanism.java:2803)
    at org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.selectOneRow(ExpressionQueryMechanism.java:2756)
    at org.eclipse.persistence.queries.ReadObjectQuery.executeObjectLevelReadQuery(ReadObjectQuery.java:555)
    at org.eclipse.persistence.queries.ObjectLevelReadQuery.executeDatabaseQuery(ObjectLevelReadQuery.java:1175)
    at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:904)
    at org.eclipse.persistence.queries.ObjectLevelReadQuery.execute(ObjectLevelReadQuery.java:1134)
    at org.eclipse.persistence.queries.ReadObjectQuery.execute(ReadObjectQuery.java:441)
    at org.eclipse.persistence.queries.ObjectLevelReadQuery.executeInUnitOfWork(ObjectLevelReadQuery.java:1222)
    at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2896)
    at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1857)
    at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1839)
    at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1790)
    at org.eclipse.persistence.internal.jpa.EntityManagerImpl.executeQuery(EntityManagerImpl.java:911)
    at org.eclipse.persistence.internal.jpa.EntityManagerImpl.findInternal(EntityManagerImpl.java:854)
    at org.eclipse.persistence.internal.jpa.EntityManagerImpl.find(EntityManagerImpl.java:730)
    at org.eclipse.persistence.internal.jpa.EntityManagerImpl.find(EntityManagerImpl.java:599)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
DEBUG o.s.t.jta.JtaTransactionManager - Initiating transaction commit
DEBUG o.s.t.jta.JtaTransactionManager - Creating new transaction with name [myMessageListenerContainer]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
DEBUG o.s.t.jta.JtaTransactionManager - Participating in existing transaction
TRACE o.s.t.i.TransactionInterceptor - Getting transaction for [my.transactional.messagehandler.handleMessage]
DEBUG o.s.t.jta.JtaTransactionManager - Participating in existing transaction
TRACE o.s.t.i.TransactionInterceptor - Getting transaction for [my.repository.class.method]
TRACE o.s.t.i.TransactionInterceptor - Completing transaction for [my.repository.class.method] after exception: org.springframework.dao.EmptyResultDataAccessException: ProcessableMessage with id 443e73e7-0905-416b-9e03-4aaa2bbf09fb; nested exception is javax.persistence.NoResultException: ProcessableMessage with id [message-id]
TRACE o.s.t.i.RuleBasedTransactionAttribute - Applying rules to determine whether transaction should rollback on org.springframework.dao.EmptyResultDataAccessException: ProcessableMessage with id 443e73e7-0905-416b-9e03-4aaa2bbf09fb; nested exception is javax.persistence.NoResultException: ProcessableMessage with id [message-id]
TRACE o.s.t.i.RuleBasedTransactionAttribute - Winning rollback rule is: null
TRACE o.s.t.i.RuleBasedTransactionAttribute - No relevant rollback rule found: applying default rules
DEBUG o.s.t.jta.JtaTransactionManager - Participating transaction failed - marking existing transaction as rollback-only
DEBUG o.s.t.jta.JtaTransactionManager - Setting JTA transaction rollback-only
public static <T> T mandatoryFind(EntityManager em, Class<T> type, Object id) throws NoResultException {
        T found = em.find(type, id);
        if (found == null) {
            throw new NoResultException(type.getSimpleName() +" with id "+ id);
        }
        return found;
}

它又从用@transactional(noRollbackFor=norresultexception.class)注释的类调用。异常是在一个相当正常的用例中引发的--我所困扰的是为什么事务在处理异常之前就回滚了?

共有1个答案

茹正初
2023-03-14

听起来您确实在暗中使用了JPA(基于您的调试日志)。这是一种典型的行为,然后查询单个结果。

NoResultException:

当对查询执行query.getSingleresult()或typedQuery.getSingleresult()并且没有返回结果时,由持久性提供程序引发。如果当前事务处于活动状态,则此异常不会导致将当前事务标记为回滚。

 类似资料:
  • 我有一个spring JMS侦听器,它正在侦听队列。一旦消息到达输入队列,它就会对消息进行某些处理,并将消息放入多个其他队列进行进一步处理(我们可以将这些其他队列称为输出队列)。在将消息发布到其他输出队列时,如果将消息发布到其中一个输出队列可能会由于任何原因而失败,我希望确保在失败之前完成的其他发布回滚到输出队列。基本上我想确保它是原子操作。在侦听器/容器上是否有任何注释/配置可用于在单个事务中实

  • 我正在与用propagation.requires_new注释的方法的奇怪行为作斗争。 以下是TransactionManager的日志:

  • 我有一个Spring Boot应用程序作为Spring JMS侦听器。我配置了多个数据源管理器一个用于Oracle,另一个用于DB2。 每当我启动应用程序时,jms侦听器容器都在寻找一个事务管理器bean,并在找到两个bean时给出以下错误。 我不想维护JMS事务。我如何实现它,或者我们如何禁用jms事务特性? 下面是我在我的主Spring Boot类上添加的注释。我也在使用Spring Data

  • 我正在使用版本来使用来自主题的消息。在使用者配置中,自动提交设置为,而设置为。与服务器协商为10秒。 在收到消息后,我将它的一部分保存到数据库中。我的数据库有时会非常慢,这会导致kafka侦听器会话超时: 组MyGroup得自动偏移量提交失败:无法完成提交,因为组已重新平衡并将分区分配给另一个成员.这意味着对poll()的后续调用之间的时间比配置的session.timeout.ms长,这通常意味

  • 在上面的代码中,ConstraintViolationException发生在saveTicket()方法内,saveTicket()内的dao甚至在捕获异常之前就已经回滚了它的事务(这是我所知道的),第一个没有回滚,因为它在另一个事务中。(这是我已经知道的行为)。 当我使用另一个事务性方法调用这两个预览方法(updateRequest()和saveTicket()),当saveTicket()方

  • 我们使用CDI和CMT(容器管理事务)连接到web应用程序中的数据库,并标记从前端调用的方法,这些方法需要使用以下事务: 这将创建一个新的CDI事务,但是现在如果在执行此代码块或从此方法调用的任何其他代码块时发生异常,它将抛出错误消息: 有没有办法让CDI重新抛出嵌套错误,以便您可以轻松地调试回滚的真正原因是什么? (在 Java-EE7、Glassfish 4.0、JSF 2.2.2 上运行)