• springboot基础(68):本地事务@Transactional简介


    本地事务的概念

    1. 事务

    事务指的就是一个操作单元,在这个操作单元中的所有操作最终要保持一致的行为,要么同时成功,要么同时被撤销。

    2. 本地事务

    本地事务其实可以认为是数据库提供的事务机制。说到数据库事务就不得不说,数据库事务中的四大特性:

    • A: 原子性,一个事务中的所有操作,要么全部完成,要么全部不完成
    • C: 一致性,在一个事务执行前和执行之后数据库都必须处于一致性状态
    • I : 隔离性,在并发环境中,当不同的事务同时操纵相同的数据时,事务之间互不影响。
    • D:持久性,指的是只要事务成功结束,它对数据库的所有更新都必须被永久的保存下来。
      数据库事务在实现时会将一次事务设计的所有操作全部纳入到一个不可分割的执行单元,该执行单元中的所有操作要么都成功,要么都失败,只要其中任一操作执行失败,都会导致整个事务的回滚。

    场景描述

    在单体应用中,一个转账操作,A向B转账100块,A扣100块,B增加100块,那么这两个操作是强关联,要么同时成功,要么同时失败。否则就会出现A减少了100块,而B没有变化。

    测试例子

    正常的操作

    下面的例子,用两个insert操作来进行演示,正常情况下,两个insert都能成功。

     @Override
        public void insertTest(String name1,String name2) {
            {
                //第一个操作
                User user = new User();
                user.setName(name1);
                userMapper.insert(user);
                log.info("插入数据" + JSON.toJSONString(user));
            }
            {
                //第二个操作
                User user = new User();
                user.setName(name2);
                userMapper.insert(user);
                log.info("插入数据" + JSON.toJSONString(user));
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    测试以下demo,调用插入操作,数据库可以看到增加了两条数据。
    在这里插入图片描述

    在这里插入图片描述

    发生事务问题

    从数据库查看,可以知道name长度为varchar(10),我们测试的时候,可以让name2长度超过10,此时就会发生第二个insert失败的情况,而第一个insert则成功。
    在这里插入图片描述
    我们直接让name1长度小于10位,name2长度大于10位,此时发生了异常,查看数据库,发现第一个insert的记录在数据库中可以看到,第二个insert则没有插入到数据库,这就发生了事务问题。
    在这里插入图片描述

    在这里插入图片描述

    解决事务问题@Transactional

    针对上面演示的问题,明显我们希望是两个insert同时成功或者失败,怎么解决呢?我们可以使用@Transactional注解添加在方法头上

    import org.springframework.transaction.annotation.Transactional;
    .......
    .......
    	@Transactional //开启事务
        public void insertTest(String name1,String name2) {
           //数据库操作1
           //数据库操作2
           ...
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述
    使用注解后,再次测试,同样发生了内容长度超长的问题,查看数据库,发现数据库并没有新增记录,很显然第2个insert的失败和第1个insert的成功是同一个事务,所以虽然第一个insert成功,但是第二个操作失败了,所以数据被回滚了,保证了事务的完整性,同时成功或失败。
    在这里插入图片描述
    在这里插入图片描述

    再次发一个成功的操作,查看日志插入成功,观察数据库,发现id没有25这条记录,很显然id为25这条记录实际插入过了,只不过被rollback了。这也印证了使用@Transactional可以保证本地事务,替代了原来的自己保存savepoint,再rollback的复杂操作。
    在这里插入图片描述
    在这里插入图片描述

  • 相关阅读:
    深入了解归并排序:原理、性能分析与 Java 实现
    Java_类和对象
    python基础小练习大全
    使用 Verdaccio 建立私有npm库
    面试题:深拷贝方法、for in 和for of区别 、this指向、改变this指向
    2024年csdn最新最全面的fiddler教程【1】
    初创公司用“豆包”大模型,日均tokens两个月内增长357倍
    tf.compat.v1.global_variables
    你安全吗?丨点击“不明链接”后果是什么你知道吗?
    492.构造矩形
  • 原文地址:https://blog.csdn.net/u011628753/article/details/126817391