事务
只要记录,事务的基本属性、事务的隔离级别、事务的传播行为
事务的基本属性
- 原子性:在一个事务中的所有操作,整体不可拆分,要么全部成功,要么全部失败。
- 一致性:事务前后,数据保持一致,比如:A转账给B,事务结束,A、B的总钱数不变。
- 隔离性:事务之前相互隔离,当然此时就会产生事务隔离级别了。
- 持久性:事务完成以后,所有的数据都将持久到数据库中。
事务的隔离级别
- 读未提交:读取到了他人未提交的数据,产生脏读。
- 读已提交(不可重复读):oracle\sqlserver默认隔离级别,读取到他人已提交的数据,但同时无法避免在二次读取中数据被修改的风险,造成两次读到结果不一致,【主要受修改操作影响】。
- 可重复读:mysql默认隔离级别,在开始读取数据(事务开启)时,不再允许修改操作,但是无法避免新增和删除风险,最终读读到的数据多了或者少了,造成幻读。【主要受增删操作影响】。
- 串行化:事务开始时,不允许其他任何操作,保证事务不会出现任何类似脏读,幻读等问题,但验证影响效率,一般不使用。
- 注:事务隔离级别可在方法的@transactional注解中通过isolation属性进行动态调整。
事务的传播行为
传播行为分为七种:
- 1、PROPAGATION_REQUIRED:如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,Spring默认的事务传播行为。
- 2、PROPAGATION_SUPPORTS:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就以非事务执行。(有则加入,没有就不管了,非事务运行)。
- 3、PROPAGATION_MANDATORY:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常。(有则加入,没有异常)。
- 4、PROPAGATION_REQUIRES_NEW:创建新事务,无论当前存不存在事务,都创建新事务。(需要新的,不管有没有,直接创建新事务)。
- 5、PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。(不支持事务,存在就挂起)。
- 6、PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。(不支持事务,存在就异常)。
- 7、PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则按REQUIRED属性执行。(存在就在嵌套的执行,没有就找是否存在外面的事务,有则加入,没有则新建)。
- 注意:常用的传播行为1,4,但注意方法在同一个service下,默认都在主方法的事务中,其他方法上的注解无效,如果想产生效果,可以使用aspectJ进行事务代理,需要引入包spring-boot-starter-aop,启动类开启注解【@EnableAspectJAutoProxyr(exposeProxy = true)】,同时在service中通过
OrderServiceImpl orderService = (OrderServiceImpl) AopContext.currentProxy()注入自己,然后才能正常使用方法自身对应的事务注解。
@Service
public class AServiceImpl extends ServiceImpl<AMapper, A> implements IAService {
AServiceImpl aService = (AServiceImpl) AopContext.currentProxy();
@Transactional
public void a(){
//b,c方法事务跟随a,因为在同一个service下
b();
c();
//b方法事务跟随a,c事务独立创新新的属于自己的事务,因为不在同一个service下
bService.b();
cService.c();
//b方法事务跟随a,c事务独立创新新的属于自己的事务,因为使用了aspectJ做代理,同时不会产生循环依赖的问题。
aService.b();
aService.c();
}
@Transactional(propagation = Propagation.REQUIRED)
public void b(){
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void c(){
}
}