• @Trasactional 事务解读


    1.知识回顾

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

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

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

    import org.springframework.transaction.support.TransactionTemplate;
    
    @Autowired
    private TransactionTemplate transactionTemplate;
    
    public void doSomething () {
        transactionTemplate.execute(status->{
            // TODO: 事务内逻辑
        });
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    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);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    调用 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

  • 相关阅读:
    Java文件操作【教你用Java运行微信】
    解读RSAC 2022 | 深度学习是不是应该深度应用到网络安全?
    Ubuntu 系统安装 VS Code 并配置 C++ 环境
    Java--正则表达式
    2023年PMP考试重要时间节点来了!别说没提醒你!
    C++ 对象模型浅析
    股票分时成交明细接口的数据怎么看?
    Spring注解
    使用IDEA开发JavaWeb项目的基本配置最新教程
    Sublime下运行javascript,并带彩色提示
  • 原文地址:https://blog.csdn.net/qq_33204709/article/details/126888992