一、事务的定义和意义事务的定义
事务的定义
将⼀组操作封装成⼀个执⾏单元(封装到⼀起),要么全部成功,要么全部失败。
简单来说:事务诞生的目的就是为了把若干个独立的操作给打包成一个整体。
我们需要注意的是: Spring 的事务 相比于 MySQL 中的事务,要复杂一些!
MySQL 的事务 无非就是 事务可以并发执行,需要考虑隔离性的问题。
但是!MySQL 的事务 非常单纯!
它不会说出现事务嵌套的问题。
比如:事务 A 嵌套了 事务 B,事务 B 嵌套了 事务 C,事务 C。。。。。
这种情况,在MySQL事务中是不会出现的。
Spring 的事务,就大不一样了!
因为我们代码,通常完成一个业务逻辑(事务),需要调用多个方法(事务),才能执行。
而多个多个方法又可能依赖于其他的方法,才得以实现。
这种情况,在 代码中 是非常常见的。
如果程序中出现这中嵌套的现象的话。
没问题的话,那还好,没有问题,
但是!万一出现了问题,那我们其它事务(方法)应该怎么去处理呢?
是相互不影响吗? 一个事务(方法)出现了问题,其它的事务不受影响。
还是 “引火上身”呢?一个事务牵扯到 ABC 三个事务,如果 一个事务出现了问题,其它的事务是是无法执行的,直接给你 进行 事务回滚了!
这个就涉及到 Spring 事务传播的机制是怎么设置的了
二、事务的实现
1、MySQL事务的回顾
详见MySQL的索引与事务(面试必考) - 细节狂魔_Dark And Grey的博客-CSDN博客
2、Spring声明式事务(利⽤注解⾃动开启和提交事务)
前置知识及概念
Spring 中的事务操作分为两类:
1、编程式事务(⼿动写代码操作事务)
编程式事务:通过代码来控制事务的 开启 和 提交,或者是 回滚。
2、 声明式事务(利用注解自动开启和提交事务)
声明式事务的实现很简单,只需要在需要的⽅法上添加 @Transactional 注解就可以实现了,⽆需⼿动开启事务和提交事务,进⼊⽅法时⾃动开启事务,⽅法执⾏完会⾃动提交事务,如果中途发⽣了没有处理的异常会⾃动回滚事务
默认情况下,只有来自外部的方法调用才会被AOP代理捕获,也就是,类内部方法调用本类内部的其他方法并不会引起事务行为,即使被调用方法使用@Transactional注解进行修饰。
@Transactional 可以⽤来修饰⽅法或类:
修饰⽅法时:需要注意只能应⽤到 public ⽅法上,否则不⽣效。推荐此种⽤法。
修饰类时:表明该注解对该类中所有的 public ⽅法都⽣效。
Spring的事务管理默认是针对***unchecked exception**回滚,也就是默认对Error异常和RuntimeException异常以及其子类进行事务回滚,且必须抛出异常,若使用try-catch对其异常捕获则不会进行事务回滚操作
因此
对于unchecked exception(Error和RuntimeException异常)抛出时不需要方法调用throws或try-catch语句
而checked exception 则必须用try语句块进行处理或者把异常交给上级方法处理,总之就是必须写代码处理它,所以必须在service捕获异常,然后再次抛出,这样事务方才起效。
关于异常详情见:异常
实例分析:事务的回滚
我们通过url模拟添加操作
那么如果出现了异常,数据库中会不会添加这一条就记录呢?
可以看到,我们再浏览器的url输入的lisi这条记录,没有成功添加到数据库中。
原因就是@Transactional 注解的自动回滚操作——》通过该注解,我们⽆需⼿动开启事务和提交事务,进⼊⽅法时⾃动开启事务,⽅法执⾏完会⾃动提交事务,如果中途发⽣了没有处理的异常会⾃动回滚事务
🔔特殊情况(无自动回滚)
我们再浏览器里继续上面的操作(尝试添加一条lisi的记录,看看有什么变化)
可以看到数据库中有了lisi这条数据——》@Transactional 在异常被捕获的情况下,不会进⾏事务⾃动回滚。
🔔事务不会⾃动回滚解决⽅案
解决⽅案1:对于捕获的异常,事务是会⾃动回滚的,因此解决⽅案1就是可以将异常重新抛出
- 解决⽅案2:⼿动回滚事务,在⽅法中使⽤ TransactionAspectSupport.currentTransactionStatus() 可以得到当前的事务,然后设置回滚⽅法 setRollbackOnly 就可以实现回滚
🔔@Transactional工作原理
@Transactional 是基于 AOP 实现的,AOP ⼜是使⽤动态代理实现的。如果⽬标对象实现了接⼝,默认情况下会采⽤ JDK 的动态代理,如果⽬标对象没有实现了接⼝,会使⽤ CGLIB 动态代理。
@Transactional 在开始执⾏业务之前,通过代理先开启事务,在执⾏成功之后再提交事务。如果中途遇到的异常,则回滚事务。
@Transactional 实现思路预览: