java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > spring管理事务

深入理解spring如何管理事务

作者:小贝壳O.o

文章详细介绍了Spring框架中的事务管理机制,包括事务的基本概念、事务管理的两种方式、Spring事务管理的整体架构、事务配置、声明式事务的实现原理、事务的关键流程、事务属性与配置,以及实际开发中常见的事务问题和解决方案,感兴趣的朋友一起看看吧

Spring 事务管理概述

最先需要明确一点的是,事务只是数据库中的一个概念,我们的java程序和数据库进行连接,java程序只是作为数据库的客户端,本质是通过网络连接对象connection来间接的操作数据库对sql进行事务开启,提交或者回滚。在 Spring 中,事务管理通常分为两种方式:编程式事务声明式事务。其中,声明式事务(基于注解 @Transactional)是最常用、最直观的做法。本质上,Spring 通过 AOP(面向切面编程)代理机制 来拦截方法调用,在方法执行前后自动开启、提交或回滚事务。

1. Spring 事务管理的整体架构

1.1 PlatformTransactionManager接口

1.2 事务配置(Transaction Configuration)

1.3 声明式事务(@Transactional)

1.4 事务增强(Advice)

2. Spring 事务管理的关键流程

以下主要针对 声明式事务(基于注解)进行说明:

2.1 Bean 初始化阶段

2.2 方法调用拦截(AOP 代理)

2.3 执行目标方法

在事务已开启(或已决定加入现有事务)的前提下,代理对象通过反射调用目标 Bean 的真实方法。目标方法中执行数据库操作(或其他资源操作),如果抛出异常,Spring 会捕获并根据 rollback rules(例如:RuntimeExceptionError 默认回滚等)决定是否回滚。

2.4 提交或回滚事务

2.5 释放资源

3. 事务属性与配置

在使用 @Transactional 注解时,可以指定多个属性来控制事务行为,比如:

@Transactional(
    propagation = Propagation.REQUIRED,
    isolation = Isolation.DEFAULT,
    timeout = 30,
    readOnly = false,
    rollbackFor = {Exception.class},
    noRollbackFor = {CustomException.class}
)
public void doSomething() {
    // ...
}

propagation - 事务传播级别
常见值:REQUIREDREQUIRES_NEWSUPPORTSMANDATORYNESTED 等,决定当前方法是否需要在已有事务中执行,或新开一个事务等。

isolation - 事务隔离级别
READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE,决定事务间读写数据的可见性,防止脏读、不可重复读、幻读等。

timeout - 超时时间
指定事务执行的最大时间(秒),超过时间未完成则抛出超时异常并回滚。

readOnly - 只读标志
指示该事务主要用于查询操作,可能在某些情况下允许数据库做额外优化;某些数据库会忽略此配置。

rollbackFor / noRollbackFor - 回滚策略
指定哪些异常抛出时应回滚或不回滚;默认对 运行时异常 和 错误 回滚,对编译异常 不回滚。

4. 实际开发中事务的常见问题

同类方法相互调用失效
如果在方法 A 内部调用方法 B,而 B 也使用了 @Transactional,但这两者都属于同一个类,则 B 的事务不会被代理拦截,导致事务注解失效。可以通过将 B 提取到另一个 Bean 或使用 AspectJ 等方式解决。

异常类型导致事务不回滚
Spring 默认对 RuntimeExceptionError 回滚,而对受检异常(Checked Exception)不回滚,需要在注解中显式指定 rollbackFor。不小心抛出了“错误类型”的异常,就可能导致事务回滚意外。

读写操作混用导致性能或数据一致性问题
@Transactional(readOnly = true) 仅作提示,不会强制阻止写操作。如果在此事务中执行了写操作或忘记设置 readOnly = false,就可能引发数据不一致或性能问题。

事务传播属性配置不当
如果不小心将一个需要新事务的操作配置为 Propagation.REQUIRED 而不是 REQUIRES_NEW,或者反之,则会导致事务边界不符预期,进而出现脏数据、锁竞争等问题。

大事务导致锁竞争
在实际项目里,如果单次事务持续时间过长,可能会长时间占用数据库锁,导致锁竞争或死锁;需注意将大事务拆分或优化为多次小事务。

多线程/异步场景下无法共享事务
Spring 的默认事务机制基于 ThreadLocal 绑定连接,异步任务或多线程无法复用同一事务,如果你在一个方法里开启多线程进行并发数据库操作,子线程无法直接继承主线程的事务上下文,会拿不到同一个 Connection。

5.spring声明式事务执行过程示例图

6.总结

核心原理

Spring 通过 AOP 代理 拦截带有 @Transactional 的方法,在方法执行前后,根据注解属性和底层 PlatformTransactionManager 自动开启、提交或回滚事务。

关键组件

同一事务内,所有数据库操作都共享此 Connection)

事务配置

可自定义传播级别隔离级别超时回滚策略等,以满足不同的业务需要。

到此这篇关于spring如何管理事务的文章就介绍到这了,更多相关spring管理事务内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文