• Spring事务和事务传播机制


    Spring事务和事务传播机制

    1.什么是事务

    指的是一系列的操作或步骤,这些操作要么全部完成、要么全部不完成。对于数据库而言、一系列操作数据库的SQL语句就是一个事务,这些SQL语句只能同时执行成功或失败。

    事务的特性:ACID

    1. 原子性:事务是不可分割的单位,一个事务中所有的操作要么成功、要么失败。
    2. 一致性:事务提交前后符合我们预设的规则,数据的完整性不能被破坏。(例如A有100元,B有100元,A向B转账了50元,A现在50元,B现在150元,它们总和是一致的)
    3. 隔离性:允许多个事务同时对数据进行读写的能力,隔离性可以防止多个事务交叉执行从而导致数据不一致的问题。
    4. 持久性:事务一旦被提交,对数据的修改就是永久的。

    没有事务的隔离性可能会有什么问题?

    1. 脏读:事务A读取到了事务B还未提交的数据,但是B事务又进行了回滚,导致A事务读取到的数据是错误的。
    2. 不可重复读:一个事务两次查询的结果不同,在两次查询的过程中,有一个事务将数据修改了。
    3. 幻读:一个事务两次查询的结果集不同,在两次查询的过程中,有一个事务新增了一部分数据。

    事务的隔离级别:

    1. 读未提交:一个事务可以看到还未被提交的事务数据。
    2. 读已提交:一个事务只能看到已经提交的事务数据,因此可以解决脏读问题。
    3. 可重复读:一个事务可以查看到其他事务已经提交的修改记录,看不到其他事务对已有记录的更新,因此每次查询的结果都是相同的,可以解决不可重复读的问题。
    4. 序列化:事务最高隔离级别,他会强制将事务进行排序,因此事务就不会发生冲突,从而解决了脏读、不可重复读、幻读问题。

    Spring事务的分类:

    1. 编程式事务(手动的进行创建、提交/回滚事务)
    2. 声明式事务(使用注解自动的实现事务的创建、提交/回滚)。

    事务的操作流程:

    1. 开启事务(start transaction)
    2. commit(提交事务)
    3. rollback(回滚事务)

    2.Spring编程式事务的实现

    DataSourceTransactionManager是一个Spring的事务管理器,它使用数据源来管理事务。这个事务管理器在事务开始时,会得到一个数据库连接,允许事务的创建、提交/回滚。

    TransactionDefinition 用于定义事务的特性,创建一个事务。

    
    @SpringBootTest
    class UserMapperTest {
        @Autowired
        private UserMapper userMapper;
    
        @Autowired
        private DataSourceTransactionManager transactionManager;
    
        @Autowired
        private TransactionDefinition definition;
    
        @Test
        void addUser() {
            //开启事务
            TransactionStatus transactionStatus = transactionManager.getTransaction(definition);
            //执行操作
            int result = userMapper.addUser("mary","123",null);
            System.out.println(result);
            //提交事务
            transactionManager.commit(transactionStatus);
            //回滚事务
            //transactionManager.rollback(transactionStatus);
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    3.声明式事务

    @Transactional:

    1. 用于方法:只能应用再public方法上,表示进入方法时自动开启事务、结束方法时自动提交事务(方法内没有产生异常才会提交)
    2. 用于类:表示执行该类中的任一public方法,都会开启和提交事务。
    public class UserController {
        @Autowired
        private UserMapper userMapper;
    
        @Transactional(rollbackFor = Exception.class)
        @RequestMapping("/add")
        public int addUser(String username, String password, String avatar){
            if(!StringUtils.hasLength(username) || !StringUtils.hasLength(password)){
                return -1;
            }
    
            int result = userMapper.addUser(username, password, avatar);
    
            try{
                //捕获可能产生的异常...
            }catch (Exception e){
                //手动进行回滚
                log.error(e.toString());
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return -2;
            }
    
            return result;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    当方法对外抛出了异常,如果程序没有处理且抛出的异常和声明rollbackfor参数匹配,Spring会将这个事务标记为回滚。事务管理器最终会实现对这个事务的回滚。

    @Transactional:注解的参数

    @Target({ElementType.TYPE, ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Inherited
    @Documented
    public @interface Transactional {
        //当存在多个事务管理器时指定使用哪一个事务管理器
        @AliasFor("transactionManager")
        String value() default "";
    
        //当存在多个事务管理器时指定使用哪一个事务管理器
        @AliasFor("value")
        String transactionManager() default "";
    
        String[] label() default {};
    	
        //事务的传播行为
        Propagation propagation() default Propagation.REQUIRED;
    
        //事务的隔离级别
        Isolation isolation() default Isolation.DEFAULT;
    
        //事务的超时时间,超时会自动进行回滚,默认值为-1表示没有超时时间,
        int timeout() default -1;
    
        String timeoutString() default "";
    
        //指定事务是否为只读事务
        boolean readOnly() default false;
    
        //用于指定能够出发事务回滚的异常类型,可以指定多个异常类型
        Class<? extends Throwable>[] rollbackFor() default {};
    
        //用于指定能够出发事务回滚的异常类型,可以指定多个异常类型
        String[] rollbackForClassName() default {};
    
        //抛出指定的异常类型,不回滚事务
        Class<? extends Throwable>[] noRollbackFor() default {};
    
        //抛出指定的异常类型,不回滚事务
        String[] noRollbackForClassName() default {};
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    4.Spring事务的隔离级别

    1. Isolation.DEFAULT:以连接的数据库的事务隔离级别为主。
    2. Isolation.READ_UNCOMMITTED:读未提交
    3. Isolation.READ_COMMITTED:读已提交
    4. Isolation.REPEATABLE_READ:可重复读
    5. Isolation.SERIALIZABLE:串行化

    在Spring的声明式事务中,只需要将其配置在@Transaction注解中。

    5.Spring事务的传播机制

    主要解决一个多个事务相互调用时,事务是如何在这些方法间进行传播的以及它们之间的影响。

    举一个例子:将购物车的商品支付购买

    在这里插入图片描述

    5.1事务的传播机制

    1. REQUIRED:默认的事务传播级别,表示如果当前存在事务,则加入该事务,如果当前没有事务,则创建一个新的事务。
    2. SUPPORTS:如何当前存在事务,则加入该事务,如果当前没有事务则以非事务的方式运行。
    3. MANDATORY:如果当前存在事务,则加入该事务,如果当前没有事务,则抛出异常。
    4. REQUIRE_NEW:如果当前存在事务,则把当前事务挂起,创建一个新事务,如果当前不存在事务,创建一个新事务。
    5. NOT_SUPPORTED:如果当前存在存在事务,则把当前事务挂起,以非事务方式运行。
    6. NEVER:如果当前存在事务,则抛出异常,不存在事务,以非事务方式运行。
    7. NESTED:如果当前存在事务,则创建一个事务作为当前事务的嵌套来运行,如果当前没有事务,则和REQUIRED相同。

    加入事务和嵌套事务:

    1. 加入事务可以理解为将当前事务的sql语句添加到上一个事务中。要么所有的SQL语句全部执行成功,要么都不执行。
      非事务方式运行。
    2. NEVER:如果当前存在事务,则抛出异常,不存在事务,以非事务方式运行。
    3. NESTED:如果当前存在事务,则创建一个事务作为当前事务的嵌套来运行,如果当前没有事务,则和REQUIRED相同。

    加入事务和嵌套事务:

    1. 加入事务可以理解为将当前事务的sql语句添加到上一个事务中。要么所有的SQL语句全部执行成功,要么都不执行。
    2. 嵌套事务可以理解为将在当前事务内部再开启一个事务,如果进行回滚只能影响到自己,而不会影响到嵌套外的事务。但是嵌套事务和外部事务时一起提交的。也就是说外部事务可以影响内部事务的提交。
  • 相关阅读:
    Q41F-40C手动球阀型号解析
    简单的股票行情演示(一) - 实时标的数据
    大厂面试题:【SpringBoot篇面试题:1-5题】
    GrabCut算法详解:从GMM模型说起
    js回到顶部或定位到指定元素
    Python OpenCV实现文档自动矫正(含源码和测试数据)
    unicodedata.normalize ——Unicode字符串标准化
    感恩节跟进技巧(附邮件模板)
    听我一句劝,业务代码中,别用多线程。
    finetune一个GPT3模型
  • 原文地址:https://blog.csdn.net/qq_52763385/article/details/133387048