编程式事务,更加精细化的控制

在某些情况下,你会发现虽然使用了 @Transactional 注解 但是事务并没有回滚,后面的逻辑依旧继续执行了,为什么呢?

声明式事务注解为什么失效了

声明式事务失效的原因,主要由以下几点构成:

  • 方法可见性@Transactional 仅在 public 方法上生效
  • 自调用 :当类中的方法是通过调用同一个类当中的另外一个 @Transactional 方法的时候,事务可能不会生效。这是因为这个事务注解是通过 AOP 实现的,而 Spring 的 AOP 代理机制在这种情况下不会触发。
  • 异常处理 :只有 RuntimeExceptionError 类型的异常会触发事务回滚。如果抛出的是 checked exception,事务不会回滚,除非指定 rollback 属性
  • 代理对象 :确保是在 Spring 管理的代理对象上调用方法,如果直接使用 new 关键字实例化的对象(未被 Spring 管理),那么 Spring 的 AOP 代理机制不会触发

什么是编程式事务?有哪些优点?

编程事务(Programmatic Transaction)是一种通过代码显式地管理事务的方式,而不是依赖声明式事务(Declarative Transaction)中使用的注解或者 xml 配置,在编程式事务中,开发人员通过编写代码来开启、提交和回滚事务,以精细控制事务的边界和行为

编程式事务的优点:

  • 精细控制:编程事务允许开发者通过代码精细地控制事务的生命周期,包括开始、提交和回滚。可以更加具体业务需求,灵活地管理事务
  • 动态处理:在允许时可以根据业务逻辑的不同情况,动态决定事务的行为。特别适合需要在代码执行过程中,根据某些条件来开启、提交或者回滚事务的场景。
  • 适用于复杂事务:在一个方法中需要多次开启和关闭事务,或需要嵌套事务的复杂场景中,编程事务可以提供更大的灵活性和控制力
  • 灵活性高:能够在代码中实现复炸的事务逻辑,可以精确控制事务的边界和行为,这在需要多个步骤或调用之间共享事务上下文的时候非常有用
  • 性能提升:通过精细化控制事务的边界,减少不必要的事务开启和提交,从而减少事务开销;通过明确事务的开始和结束,可以确保事务范围尽可能的缩小,减少长时间占用数据库资源,提高系统的并发性,通过灵活的事务管理,可以在必要时才进行事务回滚,减少回滚操作带来的性能开销。

编程式事务的缺点:

  • 代码入侵性强(核心劣势) :事务逻辑与业务 紧密耦合 在一起,业务代码中会夹杂大量的事务控制代码(比如 try-catch 中执行回滚等),这样会导致代码臃肿,可读性变差,可维护性下降
  • 开发效率低,容易出错:开发者需要手动的编写事务的开启、提交和回滚,还要处理各种异常情况,增加了开发工作量,写得越多,越容易出错
  • 代码冗余:如果多个业务都需要进行事务控制,会出现大量重复代码,违反了 DRY (Don't Repeat Yourself)原则,后期修改需要改动多出的代码
  • 对开发人员要求高:开发人员需要熟悉事务的底层原理和相关 api 的使用,必须清除什么时候该提交,什么时候该回滚。

使用示例

下面是在 SpringBoot 使用编程式事务的两种方式,示例化代码如下

第一种

java 复制代码
@Service
public class MyService {

    @Resource
    private PlatformTransactionManager transactionManager;

    @Resource
    private MyMapper myMapper;

    public void myTransactionalMethod() {
        TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());

        try {
            // 业务逻辑代码
            myMapper.insertSomething(...);

            transactionManager.commit(status); // 提交事务
        } catch (Exception ex) {
            transactionManager.rollback(status); // 回滚事务
            throw ex; // 重新抛出异常
        }
    }
}

transactionManager.getTransaction(...): 会创建一个新的事务,并返回 TransactionStatus 对象,这个对象会是当前事务的状态,用它来进行事务的提交和回滚

上述代码的核心流程:开启事务→ 执行业务逻辑 → 无异常提交 / 有异常回滚

第二种

java 复制代码
@Service
public class MyService {

    @Resource
    private TransactionTemplate transactionTemplate;

    @Resource
    private MyMapper myMapper;

    public void myTransactionalMethod() {
        transactionTemplate.execute(status -> {
            try {
                // 业务逻辑代码
                myMapper.insertSomething(...);

            } catch (Exception ex) {
                status.setRollbackOnly(); // 标记事务为回滚
                throw ex; // 重新抛出异常
            }
            return null;
        });
    }
}

TransactionTemplate 是一个简化了事务的工具类,代码编写者可以将代码重心放在业务代码上,可以更加方便的实现进行提交或者回滚,使得事务处理相关的代码更加简洁、冗余更少

总结

编程式事务是通过代码显式管理事务的方式,开发者需手动编写代码控制事务的开启、提交和回滚,而非依赖声明式事务中的注解或 XML 配置,以此实现对事务边界和行为的精细控制。

推荐使用 TransactionTemplate 进行编程式事务管理


本篇文章基于 小哈书 5.13 编写,欢迎大家访问小哈书

欢迎大家访问博主的个人博客网站 AZERL7的博客-a little world for you

相关推荐
ghie909014 小时前
基于MATLAB的TLBO算法优化实现与改进
开发语言·算法·matlab
恋爱绝缘体114 小时前
2020重学C++重构你的C++知识体系
java·开发语言·c++·算法·junit
wuk99814 小时前
VSC优化算法MATLAB实现
开发语言·算法·matlab
xiaolyuh12314 小时前
Spring 框架 核心架构设计 深度详解
spring·设计模式·spring 设计模式
AI小怪兽14 小时前
基于YOLOv13的汽车零件分割系统(Python源码+数据集+Pyside6界面)
开发语言·python·yolo·无人机
wszy180914 小时前
新文章标签:让用户一眼发现最新内容
java·python·harmonyos
Z1Jxxx14 小时前
加密算法加密算法
开发语言·c++·算法
Full Stack Developme14 小时前
数据库索引的原理及类型和应用场景
数据库
Eric.Lee202114 小时前
python实现 mp4转gif文件
开发语言·python·手势识别·手势交互·手势建模·xr混合现实
EntyIU14 小时前
python开发中虚拟环境配置
开发语言·python