标记为仅回滚的事务:如何找到原因

2022-08-31 08:52:38

我在@Transactional方法中提交事务时遇到问题:

methodA() {
    methodB()
}

@Transactional
methodB() {
    ...
    em.persist();
    ...
    em.flush();
    log("OK");
}

当我从 methodA() 调用 methodB() 时,该方法成功通过,我可以在日志中看到“OK”。但后来我得到

Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Transaction marked as rollbackOnly org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Transaction marked as rollbackOnly
    at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:521)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:393)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:120)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:622)
    at methodA()...
  1. 方法B的上下文在异常中完全丢失 - 我想这是可以的吗?
  2. 方法 B() 中的某些内容将事务标记为仅回滚?我怎样才能找到它?例如,有没有一种方法可以检查类似的东西 - 像这样,我可以逐步完成该方法并找到原因。getCurrentTransaction().isRollbackOnly()?

答案 1

当您将方法标记为 时,如果方法中出现任何异常,则会将周围的 TX 标记为仅回滚(即使您捕获了它们)。您可以使用注释的其他属性来防止其回滚,例如:@Transactional@Transactional

@Transactional(rollbackFor=MyException.class, noRollbackFor=MyException2.class)

答案 2

我终于明白了这个问题:

methodA() {
    methodB()
}

@Transactional(noRollbackFor = Exception.class)
methodB() {
    ...
    try {
        methodC()
    } catch (...) {...}
    log("OK");
}

@Transactional
methodC() {
    throw new ...();
}

发生的事情是,即使 有正确的注释,也没有。引发异常时,第二个事务仅将第一个事务标记为回滚。methodBmethodC@Transactional


推荐