Spring事务 - 防止在未经检查的异常之后回滚(RuntimeException) [英] Spring Transactions - Prevent rollback after unchecked exceptions (RuntimeException)

查看:132
本文介绍了Spring事务 - 防止在未经检查的异常之后回滚(RuntimeException)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

无法阻止事件在RuntimeException后回滚。我的环境是在Websphere 8.0上运行的Spring 4.1 + Hibernate 3.6 + JTA(WebSphereUowTransactionManager)。

首先,一个简单的例子,其行为如预期。由于我捕获了RuntimeException ,因此事务提交并且新资源已成功创建。

  @Service (fooService)
public class FooServiceImpl implements IFooService {

@Transactional
@Override
public void doStuff(Resource res){
authService.createResource (res,ADMIN);
尝试{
抛出新的RuntimeException(SOMETHING);
} catch(RuntimeException e){
e.printStackTrace();
}
}

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

  @Transactional(noRollbackFor = RuntimeException.class )
@Override
public void doStuff2(Resource res){
authService.createResource(res,ADMIN);
抛出新的RuntimeException(SOMETHING);
}

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

  @Transactional(noRollbackFor = RuntimeException.class)
@Override
public void doStuff12(Resource res) {

authService.createResource(res,ADMIN);
尝试{
res.setName(EXISTING-RESOURCE);
authService.createResource(res,ADMIN);
} catch(RuntimeException e){
e.printStackTrace();


$ / code>

尽管捕获了RuntimeException并声明了noRollbackFor 属性事务总是回滚。任何解释??



记录追踪信息:

  org.springframework .transaction.jta.WebSphereUowTransactionManager DEBUG  - 创建名为[null]的新事务:PROPAGATION_REQUIRED,ISOLATION_DEFAULT; '',+ com.myorg.webapps.exception.ElementoYaExistente 
org.springframework.transaction.jta.WebSphereUowTransactionManager DEBUG - 调用WebSphere UOW操作:type = 1,join = false
org.springframework.transaction。 support.TransactionSynchronizationManager TRACE - 初始化事务同步
org.springframework.transaction.interceptor.TransactionInterceptor TRACE - 获取[com.myorg.test.service.impl.FooServiceImpl.doStuff12]的事务
org.springframework.transaction .jta.WebSphereUowTransactionManager DEBUG - 创建名为[null]的新事务:PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
org.springframework.transaction.jta.WebSphereUowTransactionManager DEBUG - 调用WebSphere UOW操作:type = 1,join = true
org.springframework.transaction.interceptor.TransactionInterceptor TRACE - 获取[com。 myorg.authmgr.service.impl.AuthorizationServiceImpl.createResource]
org.springframework.transaction.jta.WebSphereUowTransactionManager DEBUG - 从WebSphere UOW操作返回操作:type = 1,join = true
org.springframework.transaction。 jta.WebSphereUowTransactionManager DEBUG - 创建名为[null]的新事务:PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
org.springframework.transaction.jta.WebSphereUowTransactionManager DEBUG - 调用WebSphere UOW操作:type = 1,join = true
org.springframework.transaction.interceptor.TransactionInterceptor TRACE - 获取[com。 myorg.authmgr.service.impl.AuthorizationServiceImpl.createResource]
org.springframework.transaction.interceptor.RuleBasedTransactionAttribute TRACE - 应用规则来确定事务是否应该在java.lang.Runtime上回滚:无法创建资源,它已存在:EXISTING-RESOURCE
org.springframework.transaction.interceptor.RuleBasedTransactionAttribute TRACE - 获胜回滚规则为:空
org.springframework.transaction.interceptor.RuleBasedTransactionAttribute TRACE - 未找到相关的回滚规则:应用默认值规则
org.springframework.transaction.jta.WebSphereUowTransactionManager DEBUG - 从WebSphere UOW操作返回操作:type = 1,join = true
org.springframework.transaction.jta.WebSphere UOWTransactionManager TRACE - 触发beforeCommit同步
org.springframework.transaction.jta.WebSphereUowTransactionManager TRACE - 触发beforeCompletion同步
org.springframework.transaction.support.TransactionSynchronizationManager TRACE - 清除事务同步
org.springframework。 transaction.jta.WebSphereUowTransactionManager DEBUG - 从WebSphere UOW操作返回:type = 1,join = false


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



这对我有意义:如果内部方法无法从异常中恢复,它不能恢复,并且一个外部方法不应该像没有任何事情发生一样。



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




  • 使内部方法非事务性

  • 配置内部方法不要在此异常上回滚

  • 有两个内部方法:

    • 一个是事务性的,在没有事务的情况下被调用,并且只是委托给第二个

    • 其中一个不是事务性的,并且打算作为已经存在的事务的一部分被调用


  • ul>

    I can't manage to prevent a transaction from rollingback after a RuntimeException. My env is Spring 4.1 + Hibernate 3.6 + JTA (WebSphereUowTransactionManager) running on Websphere 8.0.

    First off, a simple case that behaves as expected. Since I catch the RuntimeException, the transaction commits and the new resource is created successfully.

    @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();
            }
        }
    

    The next one is OK as well. I declare the noRollbackFor and it let's the transaction commit:

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

    And finally the problematic one. The difference is that in this case the exception is raised by the second call to authService.createResource. FYI, authService.createResource is only marked as @Transactional, so the default Propagation configuration applies and it should be joining the calling service's transaction.

        @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();
            }
        }
    

    Despite catching the RuntimeException and declaring the noRollbackFor attribute the transaction always rollsback. Any explanation??

    Log trace info:

    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
    

    解决方案

    As far as I know, as soon as a runtime exception is thrown from a transactional method and is intercepted by the transaction interceptor, the transaction is marked as rollback only. Even if this transactional method is called from another transactional method.

    This makes sense to me: if the inner method can't recover from an exception, it can't recover, and an outer method shouldn't do as if nothing happened.

    If you're expecting the transaction not to rollback, you could

    • make the inner method non-transactional
    • configure the inner method not to rollback on this exception
    • have two inner methods:
      • one that is transactional, and is intended to be called when there is no transaction yet, and which simply delegates to the second one
      • one which is not transactional, and is intended to be called as part of an already existing transaction

    这篇关于Spring事务 - 防止在未经检查的异常之后回滚(RuntimeException)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆