Spring(5) Spring中的事务@Trasactional

1.知识回顾

Spring中的事务有两种实现方式:编程式事务声明式事务

  • 编程式事务:在代码中显式地指定事务的开始、提交和回滚。
  • 声明式事务:通过 AOP 和 XML 或 @Transactional 注解来实现,使得开发人员可以将事务管理与业务逻辑解耦。

在这里插入图片描述
补充:编程式事务实现代码示例如下:

import org.springframework.transaction.support.TransactionTemplate;

@Autowired
private TransactionTemplate transactionTemplate;

public void doSomething () {
    transactionTemplate.execute(status->{
        // TODO: 事务内逻辑
        return null; // 需要的话,可以返回影响的行数或其他内容。
    });
}

2.@Transactional

@Transactionalorg.springframework 提供的 spring-tx 包中的注解,在 Mybatis Plus 包中包含该依赖。

  • 可用于修饰方法和类。修饰类时,被修饰类的所有 public 方法都会有事务,建议修饰在方法上。
  • 被修饰的方法在抛出异常之后,已经执行的sql会自动回滚。
  • 使用方式:@Transactional(rollbackFor=Exception.class)

SpringBoot 中默认开启事务。


3.rollbackFor属性

rollbackFor属性 用于指定能够触发事务回滚的一出场类型,可以指定多个,用逗号分隔。

  • rollbackFor 默认值为 UncheckedException,包括了 RuntimException 和 Error。
  • 当我们直接使用 @Transactional 不指定 rollbackFor 时,Exception 及其子类都不会触发。

请添加图片描述

补充:关于异常的知识

  • Java异常模型中,定义有 Throwable、Exception 和 Error。其中 Exception 和 Error 是 Throwable 的派生类。
  • Exception 表示由于网络故障、文件损坏、设备错误、用户输入非法等情况导致的异常,例如:NullPointerException。
  • Error 表示 Java 运行时环境出现的错误,例如:OutOfMemoryError等。

请添加图片描述

  • Exception 可以分为运行时异常(RuntimeException 及其子类)和非运行时异常(Exception 中除了 Runtime Exception 及其子类之外的类)。
  • 非运行时异常是检查异常(checked exceptions),一定要 try/catch,因为这类异常是可预料的,编译阶段就检查的出来。
  • Error 和运行时异常就是非检查异常(unchecked exceptions),不需要 try/catch,因为这类异常是不可预料的,编辑阶段不会检查。

rollbackFor 实验结果:

  • 不加 rollbackFor 属性,抛出 RuntimeException,正常回滚;
  • 不加 rollbackFor 属性,抛出 IOException,不回滚;
  • 不加 rollbackFor 属性,抛出 OutOfMemoryError,正常回滚;
  • 加上 rollbackFor=Exception.class 属性,抛出 IOException,正常回滚;
  • 加上 rollbackFor=Exception.class 属性,抛出 OutOfMemoryError,正常回滚

rollbackFor 实验结果说明:

  1. 不加 rollbackFor,使用默认值,当出现检查时异常,不会回滚
  2. rollbackFor=Exception.class 不会覆盖 Error 的回滚
  3. 综上所述,推荐使用: @Transactional(rollbackFor=Exception.class)

4.@Transactional 的实现原理

@Transactional 是 通过 AOP 的方式来实现管理事务的,具体来看如下代码:

在这里插入图片描述

事务aop处理类 TransactionInterceptor

package org.springframework.transaction.interceptor;

@SuppressWarnings("serial")
public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {
    

	@Override
	@Nullable
	public Object invoke(MethodInvocation invocation) throws Throwable {
		// Work out the target class: may be {@code null}.
		// The TransactionAttributeSource should be passed the target class
		// as well as the method, which may be from an interface.
		Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);

		// Adapt to TransactionAspectSupport's invokeWithinTransaction...
		return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
	}
}

调用 TransactionAspectSupportinvokeWithinTransaction 分三种情况:

  1. 响应式编程事务处理
  2. 命令式编程事务处理
  3. 没有事务的方法处理

5.@Transactional 的事务传播行为

实验过程: 这里主要是通过一系列实验来了解@Transactional的事务传播,过程为父方法-调用->子方法,通过分别在父方法和子方法中添加注解和抛出异常来进行测试。

实验结果:(Service内相互调用)
(根据AOP原理,Service间相互调用@Transactional注解修饰的方法事务是生效的)

实验说明:

  • 事务是否回滚,取决于是否是跨实体调用,只有跨实体调用的方法事务才生效
  • 因为 Spring 的事务是基于 AOP 的,只有当第一个 Service 有 @Transactional 注释的话,才会在开始执行 DML 之前进入切面来开启事务;
  • 如果第一个 Service 没有 @Transactional 注释的话,就已经从切面进入到服务中了,在第一个方法调用第二个方法的时候是服务内部的调用,并不会经过切面,所以就算执行 DML 之后抛出异常了,也不会回滚。

6.补充:12种@Transactional事务失效场景

请添加图片描述

整理完毕,完结撒花。





参考地址:
1.@Transaction 源码解析:https://blog.csdn.net/shandian534/article/details/124085838
2.@Transactional(rollbackFor):https://blog.csdn.net/qq_43900956/article/details/120993392
3.@Transactional 注解的 rollbackFor 属性:https://www.jianshu.com/p/c5988db897fc
4.啪!啪!@Transactional 注解的12种失效场景,这坑我踩个遍:https://blog.51cto.com/u_14787961/4833414

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不愿放下技术的小赵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值