当前位置: 首页 > news >正文

SpringBoot中的事务

事务

Springboot有3种技术方式来实现让加了@Transactional的方法能使用数据库事务,分别是"动态代理(运行时织入)"、“编译期织入”和“类加载期织入”。这3种技术都是基于AOP(Aspect Oriented Programming,面向切面编程)思想。(在网上看了很多文章,大家伙儿都把AOP称之为一种技术,其实不然,AOP并不特指一种技术,而是一种编程范式,基于AOP编程范式,不同的编程语言都有自己的实现。)

在开发中,尤其要针对多表操作的时候,要注意事物的原子性,举个例子:

在转账模块,A向B转账100元,表设计为A与B为同一个表,但是A转账之后要将A的金额-100,B的金额+100。

这时候如果不考虑原子性的话,那么更新A的数据成功了,而更新B表失败了,就会导致A的钱已经少了,B却没有收到,这是绝对不允许的,因此需要需要保证「转账」的原子性,「要么一起成功,要么一起失败」。使用@Transactional注解就是专门做这个的。

Transaction 方式(基于动态代理支持)

依赖


<dependency><groupId>org.springframework</groupId><artifactId>spring-tx</artifactId><version>version</version><!-- 5.2.7.RELEASE -->
</dependency>

注解
在启动类上加上@EnableTransactionManagement注解:

@SpringBootApplication
@EnableTransactionManagement
public class TransactionApplication {public static void main(String[] args) {SpringApplication.run(TransactionApplication.class, args);}
}

在需要使用到事务的地方加上@Transactional注解:

    @Transactional@GetMapping("insertExceptionT")public void insert3(){User u1 = new User();u1.setUsername("王五");u1.setPassword("123");userMapper.insert(u1);throw new RuntimeException("测试");}

测试

在测试代码中我们尝试向User表中插入User,分别创建两个接口,一个使用@Transactional注解,一个不使用,并且在两个接口运行的时候都抛出@RuntimeException,查看是否会成功。

@GetMapping("insertException")public void insert2(){User u1 = new User();u1.setUsername("李四");u1.setPassword("123");userMapper.insert(u1);throw new RuntimeException("测试");}@Transactional@GetMapping("insertExceptionT")public void insert3(){User u1 = new User();u1.setUsername("王五");u1.setPassword("123");userMapper.insert(u1);throw new RuntimeException("测试");}

分别访问两个低之后,查看MySQL数据情况:

+----+----------+----------+
| id | username | password |
+----+----------+----------+
| 10 | 李四      | 123      |
+----+----------+----------+

在这里插入图片描述
可以发现没有加@Transactional注解的方法虽然报错了,但是数据依旧插入成功,但是加了注解的方法什么数据都没有插入。

Transactional 失效场景

如果@Transaction标注的是一个私有方法的话,那么可能会导致IDEA测试的时候事务失效,具体的查看下面这篇文章吧,等有时间的时候再补充一下。

参考文章:「掘金」:SpringBoot事务使用及注意事项

http://www.lryc.cn/news/43977.html

相关文章:

  • Zookeeper客户端Curator5.2.0节点事件监听CuratorCache用法
  • C++ using:软件设计中的面向对象编程技巧
  • 修建灌木顺子日期
  • 深入学习JavaScript系列(七)——Promise async/await generator
  • Mybatis中的Map的使用和模糊查询的需求实现及其防SQL注入优化
  • 【redis】redis缓存更新策略
  • LeetCode刷题--复制带随机指针的链表
  • 关于我的第一台电脑 华硕
  • 【华为OD机试 2023最新 】 最大化控制资源成本(C++ 100%)
  • leetcode 有序数组的平方(977)
  • 文本三剑客之awk
  • RK3568平台开发系列讲解(驱动基础篇)IS_ERR函数的使用
  • 特殊的类之注解
  • 商业分享:盲盒电商开启电商新可能
  • 【计算机架构】如何计算 CPU 时间
  • 银行数字化转型导师坚鹏:银行行长如何进行数字化转型
  • N32G45x学习笔记--- gpio引脚复用
  • ArcGIS Pro中使用深度学习的高分辨率土地覆盖制图
  • 【学习笔记】「NOI2018」冒泡排序
  • 【Ruby学习笔记】3.Ruby 语法及数据类型
  • 华为OD机试题【字符匹配】用 Java 解 | 含解题说明
  • JavaScript数组对象的浅拷贝与深拷贝(二)实现对象深拷贝的方法(5种)
  • iPhone屏幕适配(之屏幕尺寸)
  • 手机变砖修复神器之 8 个的 Android手机系统修复工具
  • 稀疏矩阵(Sparse Matrix)
  • 深度学习中的损失函数
  • English Learning - L2 语音作业打卡 辅音咬舌音 [θ] [ð] Day29 2023.3.21 周二
  • 【原始者-综述】
  • C++内存模型
  • 八股+面经