spring事务传播特性_关于spring的事务的传播propagation特性

传播行为:当内部事务方法被当前事务方法(外部事务)调用时,必须指定内部事务应该如何传播。例如:方法可能继续在外部事务中运行,也可能开启一个新事务,并在自己的事务中运行。

关于事务回滚机制,我个人认为主要是看异常发生点的位置,异常发生时,还未提交的事务都会被回滚,还未运行的事务也不会被执行;而已经提交了的则不会被回滚。

事务传播行为定义内部事务如何在外部事务中运行

注意,在同一个Service中的方法互相调用时不存在事务传播,事务特性以当前事务为准(Spring同一个Bean中方法的互相调用中被调用方法的注解会失效)。只有在两个不同的Service之间调用才会有事务的传播特性。

Spring基于注解@Transactional的属性propagation属性有以下七种:

REQUIRED

默认的传播行为,如果外部事务存在,则内部事务将会在该事务中运行;否则,会启动一个新的事务。

内部方法必须在事务中运行。

REQUIRES_NEW

不论外部事务是否存在,内部事务总会开启新的事务,如果有外部事务,则将其挂起,当内部事务完成后再继续外部事务。

内部方法必须在“新事务”中运行。

SUPPORTS

如果存在一个外部事务,则内部方法在外部事务中运行。如果没有外部事务,则以非事务的执行。

内部方法不必保证一定要在事务中运行。

NOT_SUPPORTED

内部方法总是非事务地执行,并挂起任何存在的外部事务。不支持事务

MANDATORY

如果已经存在一个外部事务,则内部方法在外事务中运行。如果外部事务,则抛出异常。

内部方法必须在外部事务中运行,否则抛出异常。强制事务

NEVER

总是非事务地执行,如果存在一个活动的外部事务,则抛出异常。

必须在非事务中运行,否则抛出异常。强制非事务

NESTED

如果当前已经存在一个外部事务,那么该方法将会以嵌套子事务的方式在外部事务中运行。

子事务回滚savepoint非事务回滚,在主事务完成后才会提交或者回滚。

示例:测试代码,内部事务插入角色,外部事务插入用户。

//测试//正常操作会在数据库两个表中各插入一条记录@SpringBootTest@ComponentScanclass DemoApplicationTests {      @Autowired      UserService userService = null;     @Test      void contextLoads() {          User user = new User();            user.setName("张三");          userService.addUser(user);    }}    @Servicepublic class RoleServiceImpl implements RoleService {        @Autowired          RoleDao roleDao = null;           //内部事务          @Transactional(propagation = Propagation.REQUIRED)        @Override          public void addRole(Role role) {           roleDao.addRole(role);              throw new RuntimeException("内部事务异常");     }}   @Service  public class UserServiceImpl implements UserService {     @Autowired     UserDao userDao = null;        @Autowired       RoleService roleService = null;        //外部事务       @Transactional    @Override     public void addUser(User user) {         userDao.addUser(user);            Role role = new Role();             role.setRname("人事部");          roleService.addRole(role);//调用RoleService的方法          throw new RuntimeException("外部事务异常");       } }

一、REQUIRED

内部事务传播特性为REQUIRED时:在外部事务中运行或者开启新事务。

外部事务存在时:当外部方法或者内部方法发生异常时,因为内部事务在外部事务中运行,所以两条插入操作都会回滚,数据不会被持久化操作,因为他们是同一条事务

外部事务不存在时:外部方法异常时,对两条操作都无影响,外部方法是在无事务中运行的;而内部方法是在内部事务中运行的,内部方法异常时,内部方法是在事务中运行,因此会回滚,而外部方法是无事务的,所以不会影响插入。

二:REQUIRES_NEW

内部事务传播特性为REQUIRES_NEW时:不论是否存在外部事务,都会开启新事务。

外部事务存在时:当外部方法产生异常时,外部事务回滚,内部事务正常提交;当内部方法产生异常时,内部事务回滚,同时异常抛至外部,因此也会回滚外部事务。他们是两条事务,内部事务运行时,外部事务是被挂起的,当内部事务完成后继续外部事务。

外部事务不存在时:外部方法异常时,对两条操作都无影响,外部方法是在无事务中运行的;而内部方法是在内部事务中运行的,内部方法异常时,内部方法是在事务中运行,因此会回滚,而外部方法是无事务的,所以不会影响插入。

三:SUPPORTS

内部事务传播特性为SUPPORTS时:如果存在一个外部事务,则内部方法在外部事务中运行。如果没有外部事务,则以非事务的执行。

外部事务存在时:当外部方法或者内部方法发生异常时,因为内部事务在外部事务中运行,所以两条插入操作都会回滚,数据不会被持久化操作,因为他们是同一条事务

外部事务不存在时:内外方法均在无事务中运行。

四、NOT_SUPPORTED

内部事务传播特性为NOT_SUPPORTED时:内部方法总是非事务地执行,并挂起任何存在的外部事务

外部事务存在时:当外部方法异常时,回滚外部事务,而内部是非事务的,因此对内部事务不影响;当内部方法异常时,内部是非事务的,因此不会回滚内部事务,异常会抛至外部,回滚外部事务

外部事务不存在时:内外方法均在无事务中运行。

五、MANDATORY

内部事务传播特性为MANDATORY时:如果已经存在一个外部事务,则在外部事务中运行。如果没有外部事务,则抛出异常(强制事务)

外部事务存在时:当外部方法或者内部方法发生异常时,因为内部事务在外部事务中运行,所以两条插入操作都会回滚,数据不会被持久化操作,因为他们是同一条事务

外部事务不存在时:异常:IllegalTransactionStateException: No existing transaction found for transaction marked with propagation 'mandatory' and 外部事务会正常提交。

六、NEVER

内部事务传播特性为NEVER时:总是非事务地执行,如果存在一个活动的外部事务,则抛出异常(强制非事务)

外部事务存在时:异常:IllegalTransactionStateException: Existing transaction found for transaction marked with propagation 'never' 内外事务均不会提交。

外部事务不存在时:内外方法均在无事务中运行。

七、NESTED

内部事务传播特性为NESTED时:内部开启一个可嵌套的事务,它是已经存的外部事务的一个真正的子事务。

潜套事务开始执行时, 它将取得一个 savepoint,如果这个嵌套事务失败,我们将回滚到此 savepoint(非事务回滚),潜套事务是外部事务的一部分,只有外部事务结束后它才会被提交或回滚。

外部事务存在时:内部方法异常会回滚至savepoint,同时异常抛至外部,然后才是主事务的rollback;外部方法异常时,会回滚主事务(包括子事务的事务回滚)。外部事务不存在时:相当于REQUIRES_NEW,内部为一个新事务。

关于REQUIRES_NEW和NESTED的区别

NESTED子事务的回滚只是回滚至保存点,而非事务回滚,在主事务完成后才会被提交或者回滚。

90ad076937f99fef04734b0546bfe8b8.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值