Spring事务管理深度解析:原理、实践与陷阱

Spring事务管理深度解析:原理、实践与陷阱

一、事务基础概念

ACID原则

  • 原子性(Atomicity):事务内的操作要么全部成功,要么全部回滚
  • 一致性(Consistency):事务前后数据库状态保持一致
  • 隔离性(Isolation):并发事务间相互隔离
  • 持久性(Durability):事务提交后数据永久存储

二、Spring事务核心接口

java 复制代码
public interface PlatformTransactionManager {
    TransactionStatus getTransaction(TransactionDefinition definition);
    void commit(TransactionStatus status);
    void rollback(TransactionStatus status);
}

public interface TransactionDefinition {
    int getIsolationLevel();
    int getPropagationBehavior();
    int getTimeout();
    boolean isReadOnly();
}

三、事务配置方式

1. 声明式事务(推荐)

xml 复制代码
<!-- XML配置 -->
<tx:annotation-driven transaction-manager="txManager"/>

<bean id="txManager" 
      class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
</bean>
java 复制代码
// 注解驱动
@Configuration
@EnableTransactionManagement
public class AppConfig {
    @Bean
    public PlatformTransactionManager transactionManager(DataSource ds) {
        return new DataSourceTransactionManager(ds);
    }
}

2. 编程式事务

java 复制代码
transactionTemplate.execute(status -> {
    try {
        userDao.update(user1);
        logDao.insert(log);
        return true;
    } catch (Exception e) {
        status.setRollbackOnly();
        return false;
    }
});

四、@Transactional详解

属性配置

java 复制代码
@Transactional(
    propagation = Propagation.REQUIRED,
    isolation = Isolation.READ_COMMITTED,
    timeout = 30,
    readOnly = false,
    rollbackFor = {BusinessException.class},
    noRollbackFor = {SystemException.class}
)
public void businessMethod() { ... }

传播行为(Propagation)

行为类型 说明
REQUIRED(默认) 存在事务则加入,没有则新建
REQUIRES_NEW 总是新建事务,挂起当前事务
NESTED 嵌套事务,使用保存点实现部分回滚
SUPPORTS 存在事务则加入,没有则以非事务运行
NOT_SUPPORTED 非事务执行,挂起当前事务
MANDATORY 必须存在事务,否则抛异常
NEVER 必须非事务执行,否则抛异常

隔离级别(Isolation)

级别 脏读 不可重复读 幻读 说明
READ_UNCOMMITTED ✓ ✓ ✓ 最低隔离级别
READ_COMMITTED(默认) × ✓ ✓ 避免脏读
REPEATABLE_READ × × ✓ MySQL默认级别
SERIALIZABLE × × × 最高隔离级别

五、事务失效场景

  1. 非public方法:基于代理的AOP无法拦截private方法

  2. 自调用问题 :类内部方法调用不会经过代理对象
    解决方案 :

    java 复制代码
    @Autowired
    private ApplicationContext context;
    
    public void methodA() {
        context.getBean(ThisClass.class).methodB();
    }
  3. 异常类型不匹配:默认只回滚RuntimeException和Error

  4. 多线程调用:不同线程属于不同事务上下文

  5. 错误捕获异常 :catch后未重新抛出

    java 复制代码
    try { ... } 
    catch (Exception e) {
        // 需添加:throw new RuntimeException(e);
    }

六、高级特性

1. 事务同步

java 复制代码
TransactionSynchronizationManager.registerSynchronization(
    new TransactionSynchronization() {
        @Override
        public void afterCommit() {
            // 事务提交后操作
        }
    });

2. 多数据源事务

java 复制代码
@Bean
@Primary
public PlatformTransactionManager primaryTM(DataSource ds1) {
    return new DataSourceTransactionManager(ds1);
}

@Bean
public PlatformTransactionManager secondaryTM(DataSource ds2) {
    return new DataSourceTransactionManager(ds2);
}

// 使用指定事务管理器
@Transactional(transactionManager = "secondaryTM")
public void crossDatabaseOp() {...}

七、最佳实践

  1. 事务方法保持简短,避免远程调用
  2. 明确指定rollbackFor属性
  3. 只读查询添加@Transactional(readOnly=true)
  4. 嵌套事务使用PROPAGATION_NESTED
  5. 监控事务执行时间(超过3秒需优化)
相关推荐
小羊没烦恼!10 分钟前
关于分布式锁原理的一些学习与思考-redis分布式锁,zookeeper分布式锁
java·服务器·网络·学习·负载均衡
Fuyo_11191 小时前
C++ AVL树保姆级详解:从平衡因子到四大旋转机制
java·c++·算法
Sarvartha2 小时前
Date、LocalDate、LocalTime、LocalDateTime、DateTimeFormatter类
java
阿俊-全栈开发2 小时前
LikeShop 多商户 Java 版商城微服务模块拆分与部署架构演进实践
java·微服务·架构·likeshop开源商城·多商户源码
Wang's Blog2 小时前
Java 项目实战:交友项目 - 联系人列表
java·开发语言·交友
我命由我123452 小时前
访客系统形式(有用户概念、无用户概念)
java·开发语言·前端·javascript·python·产品运营·产品经理
香蕉大香蕉(06敬畏市场)3 小时前
MySQL 单点详解(01)
java·数据库·mysql·面试·博客·实习
LaughingZhu3 小时前
Product Hunt 热榜 2026-10-30:Empacer、Scape、Floot in ChatGPT
java·前端·数据库·人工智能·chatgpt·notion
niucloud-admin4 小时前
NIUCLOUD PHP SAAS上门家政使用文档:服务保障
java·开发语言·php
IT枫斗者枫哥4 小时前
CompletableFuture失败后返回空列表:异常没了,业务含义也变了
java·后端