【问题标题】:Spring Transactions - Prevent rollback after unchecked exceptions (RuntimeException)Spring Transactions - 在未经检查的异常(RuntimeException)后防止回滚
【发布时间】:2015-03-21 08:13:11
【问题描述】:

我无法阻止事务在RuntimeException 之后回滚。

我的环境是 Spring 4.1 + Hibernate 3.6 + JTA (WebSphereUowTransactionManager) 在 Websphere 8.0 上运行。

“doStuff”案例:有效

首先,一个表现符合预期的简单案例。由于我捕获了 RuntimeException,事务提交并成功创建了新资源。

@Service("fooService")
public class FooServiceImpl implements IFooService {

    @Transactional
    @Override
    public void doStuff(Resource res){
        authService.createResource(res, "ADMIN");
        try {
            throw new RuntimeException("SOMETHING");
        } catch (RuntimeException e) {
            e.printStackTrace();
        }
    }

“doStuff2”案例:有效

下一个也可以。我声明了 noRollbackFor 并让我们提交事务:

    @Transactional(noRollbackFor=RuntimeException.class)
    @Override
    public void doStuff2(Resource res){
        authService.createResource(res, "ADMIN");
        throw new RuntimeException("SOMETHING");
    }

“doStuff12”案例:不起作用

最后是有问题的。不同之处在于,在这种情况下,第二次调用authService.createResource 会引发异常。仅供参考,authService.createResource 仅标记为@Transactional,因此默认传播配置适用,它应该加入调用服务的事务。

    @Transactional(noRollbackFor=RuntimeException.class)
    @Override
    public void doStuff12(Resource res){
        
        authService.createResource(res, "ADMIN");
        try{
            res.setName("EXISTING-RESOURCE");
            authService.createResource(res, "ADMIN");
        }catch(RuntimeException e){
            e.printStackTrace();
        }
    }

尽管捕获了 RuntimeException 并声明了 noRollbackFor 属性,但事务总是回滚。有什么解释吗??

日志跟踪信息:

org.springframework.transaction.jta.WebSphereUowTransactionManager        DEBUG - Creating new transaction with name [null]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; '',+com.myorg.webapps.exception.ElementoYaExistente
org.springframework.transaction.jta.WebSphereUowTransactionManager        DEBUG - Invoking WebSphere UOW action: type=1, join=false
org.springframework.transaction.support.TransactionSynchronizationManager TRACE - Initializing transaction synchronization
org.springframework.transaction.interceptor.TransactionInterceptor        TRACE - Getting transaction for [com.myorg.test.service.impl.FooServiceImpl.doStuff12]
org.springframework.transaction.jta.WebSphereUowTransactionManager        DEBUG - Creating new transaction with name [null]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
org.springframework.transaction.jta.WebSphereUowTransactionManager        DEBUG - Invoking WebSphere UOW action: type=1, join=true
org.springframework.transaction.interceptor.TransactionInterceptor        TRACE - Getting transaction for [com.myorg.authmgr.service.impl.AuthorizationServiceImpl.createResource]
org.springframework.transaction.jta.WebSphereUowTransactionManager        DEBUG - Returned from WebSphere UOW action: type=1, join=true
org.springframework.transaction.jta.WebSphereUowTransactionManager        DEBUG - Creating new transaction with name [null]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
org.springframework.transaction.jta.WebSphereUowTransactionManager        DEBUG - Invoking WebSphere UOW action: type=1, join=true
org.springframework.transaction.interceptor.TransactionInterceptor        TRACE - Getting transaction for [com.myorg.authmgr.service.impl.AuthorizationServiceImpl.createResource]
org.springframework.transaction.interceptor.RuleBasedTransactionAttribute TRACE - Applying rules to determine whether transaction should rollback on java.lang.Runtime: Couldn't create the resource, it already exists: EXISTING-RESOURCE
org.springframework.transaction.interceptor.RuleBasedTransactionAttribute TRACE - Winning rollback rule is: null
org.springframework.transaction.interceptor.RuleBasedTransactionAttribute TRACE - No relevant rollback rule found: applying default rules
org.springframework.transaction.jta.WebSphereUowTransactionManager        DEBUG - Returned from WebSphere UOW action: type=1, join=true
org.springframework.transaction.jta.WebSphereUowTransactionManager        TRACE - Triggering beforeCommit synchronization
org.springframework.transaction.jta.WebSphereUowTransactionManager        TRACE - Triggering beforeCompletion synchronization
org.springframework.transaction.support.TransactionSynchronizationManager TRACE - Clearing transaction synchronization
org.springframework.transaction.jta.WebSphereUowTransactionManager        DEBUG - Returned from WebSphere UOW action: type=1, join=false

【问题讨论】:

    标签: spring hibernate websphere jta spring-transactions


    【解决方案1】:

    据我所知,一旦从事务方法中抛出运行时异常并被事务拦截器拦截,该事务就会被标记为仅回滚。即使这个事务方法是从另一个事务方法调用的。

    这对我来说很有意义:如果内部方法无法从异常中恢复,它就无法恢复,并且外部方法不应该像什么都没发生一样。

    如果您希望事务不回滚,则可以

    • 使内部方法成为非事务性方法
    • 配置内部方法不回滚此异常
    • 有两个内部方法:
      • 一个是事务性的,旨在在还没有事务时调用,它只是委托给第二个
      • 不是事务性的,旨在作为现有事务的一部分调用

    【讨论】:

    • 你说的有点道理。然而,奇怪的是加入的事务没有考虑父级的noRollbackFor=RuntimeException.class 规则。对我来说,它遵循整个事务范围的配置会更合乎逻辑......在这种情况下,内部方法必须是事务性的,并且在自己调用时必须回滚,所以我必须排除前两个建议。关于第三个,Spring 在某种程度上迫使我们在我们的 API 中提供两种实现,一种是事务性的,一种不是事务性的,以管理这种(不太常见)的情况,这很不雅
    猜你喜欢
    • 2018-07-24
    • 2018-12-24
    • 1970-01-01
    • 1970-01-01
    • 2021-03-23
    • 2021-02-22
    • 2017-12-07
    • 2020-10-18
    • 1970-01-01
    相关资源
    最近更新 更多