spring事务之传播特性

2022-03-29 14:20:07 浏览数 (1)

这个应该属于老生常谈的话题了,笔者在这里将根据具体的例子来讲解下spring的事务管理机制,希望帮助有需要的朋友,下面直接入主题:

1.基础

spring事务支持的几种传播类型:

PROPAGATION_REQUIRED、PROPAGATION_REQUIRES_NEW、PROPAGATION_NESTED、PROPAGATION_SUPPORTS、PROPAGATION_NOT_SUPPORTED、PROPAGATION_NEVER等,

本文着重讲几个常用的类型:PROPAGATION_REQUIRED、PROPAGATION_REQUIRES_NEW、PROPAGATION_NESTED以及PROPAGATION_NEVER

笔者采用的xml进行的事务配置,下面截取一部分相关配置:

代码语言:javascript复制
    <tx:advice id="xxAdvice" transaction-manager="xxTransactionManager">
        <tx:attributes>
  <tx:method name="hello*" propagation="NESTED"/>
            <tx:method name="*" propagation="REQUIRES"/>
        </tx:attributes>

    </tx:advice>

上面就是一段简单的advice配置,我们下面通过修改hello方法的事务传播特性来看下对调用者事务有何影响。

代码语言:javascript复制
class OuterClass{
@Autowired
private TestDAO testDAO;

@Autowired
private InnerClass innerClass;

@Override
public void testPropagation(User user) {
  testDAO.insertUser(user);
  try{
    innerClass.hello();
  } catch(RuntimeException e){
    // handle exception
  }

}
}
class InnerClass{
@Override
public void hello() {
  throw new RuntimeException("Rollback this transaction!");
}

}

下面我们就要看下当被调用的方法发生异常时,对被调用者事务有何影响

1.当hello方法的propagation属性设置为REQUIRED时,由于调用方已经有了事务,所以hello方法将与testPropagation方法共享一个事务(物理事务),但是在逻辑上hello方法与testPropagation将拥有自己的逻辑事务,这就意味着hello方法的事务异常会导致testPropagation方法事务也会回滚,最终导致整条物理事务执行失败(与我们平时的大多数需求相同),---需要注意的是这时候被调用方法与调用者方法必须在两个不同类中,否则不起作用!!!

2.当hello方法的propagation属性设置为NESTED时,这种传播特性是基于JDBC提供的savepoint特性,所以对其他非JDBC数据源无效。testPropagation在调用hello方法之前会保存一个savepoint,该特性会使得testPropagation方法与hello方法具有比REQUIRED更高的独立性,因为testPropagation方法里面try catch住了hello方法抛出的异常,所以hello方法会回滚,但是testPropagation方法却可以正常执行并提交事务

3.当hello方法的propagation属性设置为REQUIRES_NEW时,hello方法与testPropagation方法将会各自拥有自己的独立物理事务,这是与REQUIRED不同的地方,这一不同带来的作用可以使得hello方法回滚不影响testPropagation的外部事务执行。

4.当hello方法的propagation属性设置为NEVER时,hello方法将不在事务中执行,这样hello方法自然也就不会影响testPropagation的事务执行

注:这里需要注意的是被调用方法抛出的异常被调用者try catch住,否则外部事务因为被调用者抛出的异常也会回滚!!

0 人点赞