当前位置: 首页 > news >正文

Spring 与 MyBatis 整合时的事务管理细节

在 Spring 与 MyBatis 整合时,事务管理是确保数据一致性、隔离性和可靠性的核心环节。MyBatis 本身是一个轻量级的 ORM 框架,不直接管理事务,而是通过与 Spring 的集成,将事务的控制权交给 Spring,实现统一的事务管理机制。


🧠 一、Spring 与 MyBatis 整合事务管理的核心机制

1. 事务管理器的选择

在 Spring 中,事务的控制依赖于 PlatformTransactionManager 接口。对于 MyBatis,最常用的实现是:

org.springframework.jdbc.datasource.DataSourceTransactionManager

它负责管理基于单数据源的事务,确保事务的开启、提交和回滚。

注意:如果你使用的是多数据源或分布式事务,可以考虑 JtaTransactionManager


2. MyBatis 的 SqlSession 与 Spring 事务的绑定

MyBatis 的 SqlSession 是执行数据库操作的核心接口。在 Spring 中,为了支持事务管理,SqlSession 必须与 Spring 的事务上下文绑定,确保在同一个事务中使用相同的数据库连接。

Spring 提供了 SqlSessionTemplateSqlSessionInterceptor 来实现这一点:

  • SqlSessionTemplate:线程安全的 SqlSession 实现,内部使用 ThreadLocal 管理数据库连接。
  • SqlSessionInterceptor:拦截 SqlSession 的创建,确保其使用 Spring 管理的事务连接。

3. 事务的开启与提交

当使用 @Transactional 注解时,Spring 会:

  • 调用 DataSourceTransactionManager.getTransaction() 开启事务;
  • 在事务范围内,MyBatis 的 SqlSession 会复用同一个数据库连接;
  • 方法正常结束时调用 commit() 提交事务;
  • 方法抛出异常时调用 rollback() 回滚事务。

📦 二、整合事务管理的关键配置

1. 配置数据源(DataSource)

@Bean
public DataSource dataSource() {return DataSourceBuilder.create().url("jdbc:mysql://localhost:3306/mydb").username("root").password("123456").build();
}

2. 配置事务管理器

@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {return new DataSourceTransactionManager(dataSource);
}

3. 配置 SqlSessionFactory

@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();factoryBean.setDataSource(dataSource);factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml"));return factoryBean.getObject();
}

4. 配置 SqlSessionTemplate

@Bean
public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {return new SqlSessionTemplate(sqlSessionFactory);
}

5. 启用事务管理

@Configuration
@EnableTransactionManagement
public class TransactionConfig {
}

🔄 三、事务管理的执行流程(简化版)

@Transactional
public void someServiceMethod() {sqlSession.insert("insertUser", user);sqlSession.update("updateUser", user);
}
  1. Spring AOP 拦截方法@Transactional 注解方法被 TransactionInterceptor 拦截;
  2. 开启事务:调用 DataSourceTransactionManager.getTransaction()
  3. 获取数据库连接:Spring 从数据源中获取连接,并绑定到当前线程(ThreadLocal);
  4. 执行 MyBatis 操作SqlSessionTemplate 获取 SqlSession,内部使用 Spring 管理的连接;
  5. 提交事务:方法正常结束,调用 commit()
  6. 回滚事务:方法抛出异常,调用 rollback()

⚙️ 四、关键类与作用

类名作用
DataSourceTransactionManagerSpring 提供的事务管理器,用于单数据源事务管理
SqlSessionTemplateMyBatis 与 Spring 集成的核心类,线程安全,支持事务
SqlSessionInterceptor拦截 SqlSession 的创建,确保使用 Spring 管理的连接
SqlSessionFactoryBean用于创建 SqlSessionFactory,集成 Spring 管理的数据源
@EnableTransactionManagement启用 Spring 的事务管理功能

❗ 五、常见问题与解决方案

1. 事务失效:方法非 public

  • 原因:Spring AOP 默认只拦截 public 方法。
  • 解决:将事务方法设为 public,或使用 AspectJ 代理。

2. 事务失效:内部调用(self-invocation)

  • 原因:同一类中调用 @Transactional 方法,代理失效。
  • 解决:通过注入自身 Bean 调用:
@Autowired
private MyService self;public void outerMethod() {self.innerMethod(); // 事务生效
}

3. 事务未正确提交或回滚

  • 原因:未正确配置事务管理器或未启用事务。
  • 解决:确认已注册 DataSourceTransactionManager 并启用 @EnableTransactionManagement

4. MyBatis 操作未参与事务

  • 原因SqlSession 未使用 Spring 管理的连接。
  • 解决:确保使用 SqlSessionTemplate 或注入 Mapper 接口(推荐方式)。

✅ 六、最佳实践建议

建议说明
使用 @Transactional 注解推荐使用声明式事务,简洁易维护
使用 SqlSessionTemplate保证线程安全和事务一致性
使用 Mapper 接口注入推荐使用 @MapperScan 自动扫描 Mapper 接口
避免手动管理事务尽量避免使用编程式事务,除非有特殊需求
配置事务传播行为明确事务传播行为(如 REQUIRED, REQUIRES_NEW
异常处理明确事务回滚的异常类型(如 rollbackFor = Exception.class

🧩 七、Spring Boot 中的自动配置

在 Spring Boot 中,事务管理器和 MyBatis 的整合可以通过自动配置简化:

  • 自动配置事务管理器:Spring Boot 会根据数据源自动配置 DataSourceTransactionManager
  • 自动配置 MyBatis:使用 mybatis-spring-boot-starter,自动配置 SqlSessionFactorySqlSessionTemplate
  • 自动扫描 Mapper 接口:使用 @MapperScan 注解或 mybatis.mapper-locations 配置。

✅ 八、总结

特性Spring 与 MyBatis 整合事务管理
事务管理器DataSourceTransactionManager
事务控制基于 AOP 的声明式事务
SqlSession 管理使用 SqlSessionTemplate 或注入 Mapper 接口
事务绑定使用 ThreadLocal 管理数据库连接
自动配置Spring Boot 可自动完成大部分配置
失效场景方法非 public、内部调用、未正确配置事务管理器

http://www.xdnf.cn/news/326737.html

相关文章:

  • 如何使用docker配置ros-noetic环境并使用rviz,gazebo
  • Nvidia-smi 运行失败(Failed to initialize NVML: Driver/library version mismatch)
  • Elasticsearch 8.x 在 java 中的使用情况
  • MIT关节电机相序校准
  • upload-labs靶场通关详解:第二关
  • 绕线机的制作与研究
  • very_easy_sql(SSRF+SQL注入)
  • 配置指定地址的conda虚拟Python环境
  • gitcode 上传文件报错文件太大has exceeded the limited size (10 MiB) in commit
  • dragonfly Prometheus 没有监控指标 dragonfly_scheduler_host_traffic
  • 益鑫通连接器车规级,非车规可替代JST,MOLEX
  • Keil安装pack包时报错解决:Cannot copy license file to “.Download“ folder.
  • string--OJ3
  • 基于Django框架开发的B2C天天生鲜电商平台
  • 306.检查是否所有A都在B之前
  • 通用分布式锁组件
  • 【优化策略】离散化
  • 力扣92.反转指定范围内的链表、25.k个一组反转链表
  • SpringBoot优雅参数检查
  • java基础-数组
  • AI训练服务器概述
  • 【信息系统项目管理师】法律法规与标准规范——历年考题(2024年-2020年)
  • 【fastadmin开发实战】财务数据快速导入系统(复制导入)
  • 配置Hadoop集群-测试使用
  • C# NX二次开发:曲线和点位相关UFUN函数详解
  • 游戏中心首页
  • LeetCode:对称二叉树
  • 贵州省棒球运动发展中长期规划(2024-2035)·棒球1号位
  • MySQL 联合查询的使用教程
  • Consumer Group的作用是什么?Rebalance的触发条件有哪些? (实现消费者负载均衡;消费者加入/离开、订阅Topic变化等)