侧边栏壁纸
博主头像
牧云

怀璧慎显,博识谨言。

  • 累计撰写 85 篇文章
  • 累计创建 9 个标签
  • 累计收到 8 条评论

目 录CONTENT

文章目录

Spring事务

秋之牧云
2025-11-18 / 0 评论 / 0 点赞 / 13 阅读 / 0 字

数据库事务

数据库事务是由数据库管理系统(DBMS)提供的、满足ACID特性的操作单元:

  • 原子性(Atomicity):事务内所有操作要么全部成功,要么全部失败。

  • 一致性(Consistency):事务执行前后,数据库状态保持一致。

  • 隔离性(Isolation):并发事务互不干扰,通过隔离级别(如READ COMMITTED、REPEATABLE READ等)控制。

  • 持久性(Durability):事务提交后,数据修改永久生效。

数据库通过 BEGIN TRANSACTIONCOMMITROLLBACK 管理事务,并依赖锁机制和日志(如redo log、binlog)实现回滚与恢复 。

Spring事务和数据库事务的关系

Spring事务是对数据库事务的封装与增强,其本质仍依赖底层数据库的事务能力:

  • 若数据库不支持事务(如MySQL的MyISAM引擎),Spring事务无效 。

  • Spring通过事务管理器(如DataSourceTransactionManager)获取数据库连接,并调用JDBC的commit()rollback()完成事务操作 。

  • Spring在数据库事务基础上,增加了传播行为声明式配置跨资源协调(如JTA)等高级特性 。

Spring事务的实现原理

Spring事务主要通过AOP动态代理实现:

  • 在方法上标注@Transactional后,Spring会为该Bean生成代理对象 。

  • 调用代理方法时,Spring先关闭自动提交(setAutoCommit(false)),执行业务逻辑;若无异常则提交事务,否则回滚 。

  • 默认仅对RuntimeExceptionError回滚,可通过rollbackFor属性自定义 。

  • 支持编程式事务(手动控制TransactionStatus)和声明式事务(注解驱动)两种方式 。

  • 事务传播机制(如REQUIREDREQUIRES_NEW)决定多个事务方法间的协作方式 。

Spring事务传播行为

Spring 事务传播行为定义了当一个带有事务的方法调用另一个事务方法时,事务应如何传播。Spring 在 TransactionDefinition 接口中定义了 7 种传播行为 :

  1. PROPAGATION_REQUIRED(默认):如果当前存在事务,则加入该事务;否则创建一个新事务 。

  2. PROPAGATION_REQUIRES_NEW:总是创建一个新事务;如果当前存在事务,则将其挂起 。

  3. PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;否则以非事务方式执行 。

  4. PROPAGATION_NOT_SUPPORTED:以非事务方式执行;如果当前存在事务,则将其挂起 。

  5. PROPAGATION_MANDATORY:必须在已有事务中执行,否则抛出异常 。

  6. PROPAGATION_NEVER:必须以非事务方式执行,若存在事务则抛出异常 。

  7. PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务中执行(依赖数据库 savepoint 支持);否则行为同 REQUIRED 。

这些传播行为通过 @Transactional(propagation = ...) 注解配置,用于精确控制事务边界与隔离性,满足不同业务场景需求 。

事务传播行为举例说明

Spring 事务的传播行为定义了当一个事务方法调用另一个事务方法时,事务应如何传播。Spring 提供了 7 种传播行为,可通过 @Transactional(propagation = Propagation.XXX) 配置。以下是各项行为的代码示例说明:

  1. PROPAGATION_REQUIRED(默认)

@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {
    dao.insertA();
    methodB(); // 与 methodA 共享同一事务
}
@Transactional(propagation = Propagation.REQUIRED)
public void methodB() { dao.insertB(); }

若 methodB 抛异常,methodA 和 B 均回滚 。

  • 若当前存在事务,则加入;否则新建事务。

  1. PROPAGATION_REQUIRES_NEW

@Transactional
public void methodA() {
    dao.insertA();
    methodB(); // 挂起 A 的事务,B 独立提交
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void methodB() { dao.insertB(); }

即使 methodA 回滚,methodB 的数据仍保留 。

  • 总是新建事务,挂起当前事务(如有)。

  1. PROPAGATION_SUPPORTS

public void methodA() { // 无事务
    methodB(); // 非事务方式执行
}
@Transactional(propagation = Propagation.SUPPORTS)
public void methodB() { dao.insertB(); }

methodB 不会开启新事务 。

  • 有事务则加入,无则非事务执行。

  1. PROPAGATION_NOT_SUPPORTED

@Transactional
public void methodA() {
    methodB(); // 挂起 A 的事务,B 非事务执行
}
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void methodB() { dao.insertB(); }

methodB 的操作不受 methodA 事务控制 。

  • 以非事务方式执行,挂起当前事务。

  1. PROPAGATION_MANDATORY

public void methodA() { // 无事务
    methodB(); // 抛出 IllegalTransactionStateException
}
@Transactional(propagation = Propagation.MANDATORY)
public void methodB() { dao.insertB(); }
  • 必须在已有事务中执行,否则抛异常。

  1. PROPAGATION_NEVER

@Transactional
public void methodA() {
    methodB(); // 抛异常
}
@Transactional(propagation = Propagation.NEVER)
public void methodB() { dao.insertB(); }
  • 必须非事务执行,若存在事务则抛异常。

  1. PROPAGATION_NESTED

@Transactional
public void methodA() {
    dao.insertA();
    methodB(); // 创建保存点
    // 若 methodB 异常,仅回滚 B;若 A 异常,全部回滚
}
@Transactional(propagation = Propagation.NESTED)
public void methodB() { dao.insertB(); }

依赖数据库对 savepoint 的支持 。

  • 若存在事务,则在嵌套事务(基于保存点)中执行。

注意:以上行为均基于 Spring AOP 代理机制,且要求方法为 public 并通过 Spring 容器调用 。

Spring事务最佳实践

  • 避免在事务方法内捕获异常而不抛出:否则Spring无法触发回滚 。

  • 合理设置rollbackFor:若需对检查型异常回滚,应显式配置 。

  • 慎用REQUIRES_NEW:可能导致事务悬挂或数据不一致。

  • 注意事务边界:事务方法应聚焦于数据库操作,避免包含远程调用、耗时IO等非事务逻辑。

  • 隔离级别以Spring配置为准:若数据库不支持指定级别,则效果由数据库决定 。

  • 不要依赖事务保证业务逻辑正确性:事务仅回滚数据库操作,已执行的非DB操作(如发消息、写文件)不会回滚 。

0

评论区