Spring-事务&@Transactional事务传播

事务开启

在这里插入图片描述
数据源和事务管理平台的加载都是在类ProxyTransactionManagementConfiguration 进行的。

Connection 连接、事务、和用户会话

在spring 中事务传播属性

PROPAGATION_REQUIRED
如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常
见的选择。

PROPAGATION_SUPPORTS
支持当前事务,如果当前没有事务,就以非事务方式执行。

PROPAGATION_MANDATORY
使用当前的事务,如果当前没有事务,就抛出异常。

PROPAGATION_REQUIRES_NEW
新建事务,如果当前存在事务,把当前事务挂起。

PROPAGATION_NOT_SUPPORTED
以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

PROPAGATION_NEVER
以非事务方式执行,如果当前存在事务,则抛出异常。

PROPAGATION_NESTED
如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED 类似的操作。

传播属性的事务控制

1、获取事务属性对象在这里插入图片描述
2、tas.getTransactionAttribute
这个方法就会扫描method 上面的@Transactional 注解,把注解里面配置的属性封装到
对象中,对应的对象是:RuleBasedTransactionAttribute
在这里插入图片描述
3、开启事务
在这里插入图片描述

在这里插入图片描述
该方法判断当前是否存在事务,如果能从事务对象中拿到连接对象,就表示当前是存在事务
的。如果不存在,也就是说是第一次创建事务。则往下走:
在这里插入图片描述

第一,创建事务状态对象,事务状态就是记录事务流转过程中状态数据的,有一个数据非常
重要,直接决定了提交,回滚和恢复绑定操作,就是newTransaction 属性,这个属性要牢记。
如果为true 就代表当前事务允许单独提交和回滚,一般是第一次创建事务或者事务传播属性为
PROPAGATION_REQUIRES_NEW 的时候。如果为false 则当前事务不能单独提交和回滚。

第二,doBegin 该方法则是开启事务的核心方法
1、从数据源连接池中获取连接
在这里插入图片描述
2、把自动提交关闭
在这里插入图片描述
3、建立ThreadLocal 的绑定关系
在这里插入图片描述
doBegin 基本结束了,事务已经开启了。

注解事务和编程式事务

注解事务是方法上面加了@Transactional 的事务,这种事务控制粒度不够细,如果方法
流程很长的话会产生连接占用问题,连接占用就会导致整个系统吞吐量下降。

注解事务犹豫隔离级别的不同,可能导致可重复读的问题,比如抢火车票这种,需要用
到乐观锁,但是在重复抢票的时候由于是同一个连接对象,所以每次查询的数据是一样的。
在这里插入图片描述
用编程式事务解决了这个问题,这个查询语句是在execute 方法内,当这个方法执行完
时就提交了事务,下次再进来时又是一个单独的新事务了。

编程式事务控制粒度更细,可以只关心需要事务控制的操作,如果不需要事务控制的代
码可以不放在execute 方法内。
在这里插入图片描述

@Transactional事务的传播代码讲解

  1. 只在A方法上加 @Transactional(propagation = Propagation.REQUIRED),B方法抛异常, 事务是都回滚的。
    在这里插入图片描述
    在这里插入图片描述

在这里插入图片描述

  1. 只在B方法上加 @Transactional(propagation = Propagation.REQUIRED),B方法抛异常, A方法提交,B方法回滚。
    在这里插入图片描述
    在这里插入图片描述

在这里插入图片描述

  1. A方法 B方法都加 @Transactional(propagation = Propagation.REQUIRED) ,A方法抛异常,事务都回滚, B方法抛异常,事务都回滚
    在这里插入图片描述
    在这里插入图片描述

在这里插入图片描述
4. A方法@Transactional(propagation = Propagation.REQUIRED), B 方法@Transactional(propagation = Propagation.REQUIRES_NEW), B方法抛异常 ,事务全回滚。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
A方法抛异常, A方法回滚,B方法执行。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
5. A方法B方法都用@Transactional(propagation = Propagation.REQUIRES_NEW), B方法抛异常 ,都回滚。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
A方法抛异常 ,A回滚,B提交。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

事务失效情况

1 、@Transactional在同一个类中调用的失效问题

Spring采用动态代理(AOP)实现对bean的管理和切片,它为我们的每个class生成一个代理对象。只有在代理对象之间进行调用时,可以触发切面逻辑。
在这里插入图片描述
原因:在同一个类中的两个方法,一个方法调用另一个方法的时候,持有的引用是this,而this指向的是被代理对象,也就是原对象的引用。而其他实例调用代理类的时候,是通过代理类的切面后再去调用被代理对象的方法。
在这里插入图片描述

A B两个方法,同时开启事务。

  1. A REQUIRED B REQUIRED 开启了几个事务? 1个
  2. A REQUIRED B REQUIRES_NEW 开启了几个事务? 2个
  3. A REQUIRED B NESTED 开启了几个事务? 1个

2、@Transactional注解后未加(rollbackFor = Exception.class)

不加(rollbackFor = Exception.class)的话,当方法中报错,报错前的内容会进行提交,而不会进行回滚,也就不会达到事务的效果。

3、非public方法

spring对注解事务的方法进行校验,修饰符是不是public,不是 public则不会获取@Transactional 的属性配置信息。
在这里插入图片描述

Method visibility and @Transactional
When using proxies, you should apply the @Transactional annotation only to methods with public visibility. If you do annotate protected, private or package-visible methods with the @Transactional annotation, no error is raised, but the annotated method does not exhibit the configured transactional settings. Consider the use of AspectJ (see below) if you need to annotate non-public methods.

注解是要通过反射来实现的,反射拿不到私有方法。使用AspectJ 即可生效。
https://docs.spring.io/spring-framework/docs/current/reference/html/data-access.html#transaction-declarative-aspectj
章节:1.4.6

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值