Spring 事务实现原理,Spring 的 ACID是如何实现的?如果让你用 JDBC 实现事务怎么实现?

Spring 事务实现原理

Spring 的事务管理基于 AOP(面向切面编程)代理模式,通过以下核心组件实现:

  1. 事务管理器(PlatformTransactionManager

    Spring 提供了统一的事务抽象接口(如 DataSourceTransactionManagerJpaTransactionManager),负责实际的事务操作(开启、提交、回滚)。不同持久化框架(JDBC、JPA)有不同实现。

  2. 事务拦截器(TransactionInterceptor

    通过 AOP 动态代理,拦截带有 @Transactional 注解的方法,在方法执行前开启事务,执行后提交或回滚事务。

  3. 事务元数据(@Transactional

    注解定义事务属性(传播行为、隔离级别、超时时间、回滚条件等),Spring 根据这些元数据管理事务行为。

  4. 事务同步机制

    通过 TransactionSynchronizationManager 将事务资源(如数据库连接)绑定到当前线程,确保同一事务的多个操作共享同一资源。

Spring 如何实现 ACID?

Spring 本身不直接实现 ACID,而是 依赖底层数据库的事务能力,通过事务管理器协调数据库的事务机制:

  • 原子性(Atomicity) :通过事务管理器统一提交(commit)或回滚(rollback)所有操作。
  • 一致性(Consistency):由应用层业务逻辑和数据库约束(如唯一索引、外键)共同保证。
  • 隔离性(Isolation) :通过设置事务隔离级别(如 READ_COMMITTED),底层由数据库实现。
  • 持久性(Durability):依赖数据库的持久化机制(如 Redo Log)。

使用 JDBC 实现事务

直接使用 JDBC 手动管理事务的步骤如下:

java 复制代码
Connection conn = null;
try {
    // 1. 获取数据库连接
    conn = dataSource.getConnection();
    // 2. 关闭自动提交,开启事务
    conn.setAutoCommit(false); 

    // 3. 执行多个 SQL 操作
    Statement stmt1 = conn.createStatement();
    stmt1.executeUpdate("UPDATE account SET balance = balance - 100 WHERE user = 'A'");

    Statement stmt2 = conn.createStatement();
    stmt2.executeUpdate("UPDATE account SET balance = balance + 100 WHERE user = 'B'");

    // 4. 提交事务
    conn.commit(); 
} catch (SQLException e) {
    // 5. 回滚事务
    if (conn != null) {
        try {
            conn.rollback();
        } catch (SQLException ex) {
            ex.printStackTrace();
        }
    }
} finally {
    // 6. 关闭连接
    if (conn != null) {
        try {
            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

关键点

  • 通过 setAutoCommit(false) 手动控制事务。
  • 所有操作成功时调用 commit(),失败时调用 rollback()
  • 确保在 finally 块中释放资源,避免连接泄漏。

对比 Spring 与 JDBC 事务管理

特性 Spring 事务 JDBC 事务
抽象级别 声明式(注解)或编程式(API) 编程式(手动代码控制)
复杂度 低(自动管理) 高(需手动处理提交/回滚)
灵活性 支持多数据源、分布式事务(如 JTA) 仅限于单个数据库连接
异常处理 自动回滚特定异常(如 RuntimeException 需手动捕获异常并回滚
资源管理 自动绑定线程、释放资源 需手动关闭连接

常见问题与注意事项

  • 事务失效场景

    1. 方法非 public
    2. 自调用(类内部方法调用,绕过代理)。
    3. 异常被捕获未抛出或非 RuntimeException 未配置回滚。
  • 隔离级别与锁

    高隔离级别(如 SERIALIZABLE)可能影响性能,需权衡一致性与并发性。

  • 连接泄漏

    JDBC 中务必在 finally 块关闭连接,Spring 则通过模板类(如 JdbcTemplate)自动管理。

相关推荐
丶意冷12 分钟前
mybatisPlus分页方言设置错误问题 mybatisPlus对于Oceanbase的Oracle租户分页识别错误
java·数据库·oracle·oceanbase
要开心吖ZSH38 分钟前
《Spring 中上下文传递的那些事儿》Part 4:分布式链路追踪 —— Sleuth + Zipkin 实践
java·分布式·spring
考虑考虑1 小时前
Springboot3.4.x中的@Bean使用
spring boot·后端·spring
时序数据说2 小时前
为什么时序数据库IoTDB选择Java作为开发语言
java·大数据·开发语言·数据库·物联网·时序数据库·iotdb
戒不掉的伤怀2 小时前
【Navicat 连接MySQL时出现错误1251:客户端不支持服务器请求的身份验证协议;请考虑升级MySQL客户端】
服务器·数据库·mysql
cv高级工程师YKY2 小时前
服务器 - - QPS与TPS介绍
数据库
nbsaas-boot2 小时前
高可扩展属性建模设计:架构师的全局思考与落地方案
数据库
爱上语文3 小时前
Redis基础(5):Redis的Java客户端
java·开发语言·数据库·redis·后端
陈敬雷-充电了么-CEO兼CTO3 小时前
推荐算法系统系列>推荐数据仓库集市的ETL数据处理
大数据·数据库·数据仓库·数据挖掘·数据分析·etl·推荐算法
MeshddY3 小时前
(超详细)数据库项目初体验:使用C语言连接数据库完成短地址服务(本地运行版)
c语言·数据库·单片机