Spring事务传播机制

hi ,大家好,继续为大家带来Spring事务传播机制的相关知识
Spring事务传播机制_第1张图片

文章目录

  • 1.事务传播机制是什么
  • 2.事务传播机制作用
  • 3.事务传播机制

1.事务传播机制是什么

定义了多个包含了事务的⽅法,相互调⽤时,事务是如何在这些⽅法间进⾏传递的

2.事务传播机制作用

事务隔离级别是保证多个并发事务执⾏的可控性的(稳定性的),而事务传播机制是保证⼀个事务在多个调用方法间的可控性的(稳定性的)
Spring事务传播机制_第2张图片上面的图片很好的解释了事务传播机制和事务隔离级别的流程

3.事务传播机制

Spring事务传播机制定义了在多个事务方法相互调用时,不同事务方法间事务处理的行为方式。Spring框架提供了7种不同的事务传播行为方式,分别是:

  1. REQUIRED:默认的传播行为,如果当前存在事务,则加入该事务,否则创建一个新事务。
    Spring事务传播机制_第3张图片
    这个来通俗的解释一下,如果当前方法没有开启事务,就会创建一个新的事务,如果存在事务就会加入该事务
    Spring事务传播机制_第4张图片
    我们在用代码验证一下
    Spring事务传播机制_第5张图片
    Spring事务传播机制_第6张图片
    因为此时的级别默认是required,所以应该是一个大事务,有一个有异常 ,其余的也就添加失败
    Spring事务传播机制_第7张图片

Spring事务传播机制_第8张图片
可以从数据库中看到,并未添加数据

  1. SUPPORTS:如果当前存在事务,则加入该事务,否则不使用事务。
    Spring事务传播机制_第9张图片
    如果A 没有开启事务,那么就以非事务的方式运行,后面的方法看到该调用链没有事务就也会摆烂,因此即使报了异常,也继续添加,
    看代码
    Spring事务传播机制_第10张图片
    Spring事务传播机制_第11张图片

Spring事务传播机制_第12张图片
3 MANDATORY:当前方法必须在事务中执行,存在事务,就会加入该事务,如果不存在事务,则抛出异常。

4.REQUIRES_NEW:表示创建⼀个新的事务,如果当前存在事务,则把当前事务挂起。也就是说不管外部⽅法是否开启事务,Propagation.REQUIRES_NEW 修饰的内部⽅法会新开启⾃⼰的事务,且开启的事务相互独⽴,互不⼲扰。

5.NOT_SUPPORTED:以⾮事务⽅式运⾏,如果当前存在事务,则把当前事务挂起

6.NEVER:当前方法不能在事务中执行,如果存在事务,则抛出异常。

Spring事务传播机制_第13张图片
Spring事务传播机制_第14张图片

Spring事务传播机制_第15张图片
Spring事务传播机制_第16张图片
可以清楚的看到没有插入
在这里插入图片描述
控制台连受影响的行数都没有打印,直接抛出异常

这个NESTED比较绕,我们一起努力,冲冲冲!

7.NESTED:创建一个嵌套事务,如果当前存在事务,则将该事务作为嵌套事务的父事务,如果父事务提交,则嵌套事务会提交,否则回滚。
如果当前没有事务,则该取值等价于 PROPAGATION_REQUIRED。
执行流程
Spring事务传播机制_第17张图片

当没有事务,创建事务,后续方法会生成嵌套事务,并且有一个保存点,一旦该事务出现问题,就会回滚到上一个事务保存点,不会影响其他事务的执行

package com.example.demo.controller;

import com.example.demo.model.Userinfo;
import com.example.demo.service.UserService;
import org.apache.catalina.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.util.pattern.PathPattern;


//测试类
    @RestController
    @RequestMapping("/user")
public class UserController {
        @Autowired
 private UserService userService;
        @RequestMapping("/add")
        @Transactional(propagation = Propagation.REQUIRED)
        public  int  add(){
       Userinfo userinfo=new Userinfo();
       userinfo.setUsername("老七");
       userinfo.setPassword("123");

     int result=    userService.add(userinfo);

            System.out.println("受影响的行数是"+result);
            userService.insert(userinfo);
    

            return result;

        }
}

package com.example.demo.service;

import com.example.demo.mapper.UserMapper;
import com.example.demo.model.Userinfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class UserService {
    @Autowired
    private UserMapper userMapper;
    @Transactional(propagation = Propagation.NESTED)
    public int  add(Userinfo userinfo){
            int result=userMapper.add(userinfo);
        System.out.println("受影响的行数"+result);
     
        return  result;
    }
    @Transactional(propagation = Propagation.NESTED)
    public int insert(Userinfo userinfo){
        int result=userMapper.add(userinfo);
        System.out.println("受影响的行数"+result);
        int num=10/0;
        return  result;
    }
}

在这里插入图片描述

Spring事务传播机制_第18张图片

Spring事务传播机制_第19张图片
数据库是啥也没插入的,为啥呢?不是说会回滚到上一个事务保存点吗?所以应该插入一条,为啥一条也没有
因为:Spring事务传播机制_第20张图片
第三个出了问题,那么创建事务的作为调用方,一定可以感知到异常,那么整个事务就会回滚,所以一条都不会插入
所以某个方法报异常不要让总的调用者感知到,就不会全部回滚,那么可以采用如下方式
Spring事务传播机制_第21张图片
修改这里的代码,让该方法感知到异常即可,不让总方法感知到,那么就会执行回滚操作,回滚到上一个事务保存点,所以只会插入一条数据

Spring事务传播机制_第22张图片
在写这个例子的时候,我们特意修改,不在add方法里面调用insert方法,而是在userController中调用,为什么呢?
因为NESTED嵌套NESTED的时候,上一个NESTED保存点设置不上,这两个保存点会进行合并,合并成一个临时任务,那么一个挂掉,两个都挂了,所以在总的调用方法中调用它,才能有效果
再举一个例子:

公司雇了一个清洁工A,清洁工自己有又雇了一个清洁工B,当清洁B干了坏事,那么公司就会把A和B同时开除,当公司雇了两个清洁工,其中一个清洁工出了问题,就开掉出问题的那个就好,没出问题的留下~

这个例子就对应了代码的执行过程~

今天就讲到这里,我们下期再见,886!
Spring事务传播机制_第23张图片

你可能感兴趣的:(spring,java,数据库)