全面解析MyBatis事务管理机制,助你掌握数据一致性的核心技术
一、MyBatis整体架构与事务管理模块
在深入事务管理模块之前,我们先了解MyBatis的整体架构,以及事务管理模块在其中的重要地位。

从上图可以看出,MyBatis采用了分层架构设计,而事务管理模块(Transaction)位于基础支撑层,是保证数据一致性的关键组件。
1.1 事务管理模块的核心职责
事务管理模块主要承担以下核心职责:
✅ 管理数据库事务 - 控制事务的开始、提交和回滚
✅ 事务提交和回滚 - 根据操作结果决定提交或回滚事务
✅ 连接管理 - 获取和释放数据库连接
✅ 与不同框架集成 - 支持与Spring、Guice等框架的集成
✅ 隔离级别控制 - 支持不同的事务隔离级别
1.2 什么是事务
事务(Transaction) 是数据库操作的基本单元,包含一系列操作,这些操作要么全部成功,要么全部失败。
事务具有四个重要特性(ACID):
| 特性 | 说明 | 示例场景 |
|---|---|---|
| 原子性Atomicity | 事务中的操作要么全部成功要么全部失败 | 转账:扣款和存款同时成功或同时失败 |
| 一致性Consistency | 事务执行前后数据库状态保持一致 | 转账前后总金额不变 |
| 隔离性Isolation | 并发事务之间相互隔离 | 一个事务看不到其他未提交事务的数据 |
| 持久性Durability | 事务提交后数据永久保存 | 即使系统崩溃提交的数据也不会丢失 |
二、Transaction接口架构
MyBatis的事务管理模块采用了简洁的接口设计。

2.1 Transaction接口
Transaction是事务管理的顶层接口:
csharp
public interface Transaction {
// 获取数据库连接
Connection getConnection() throws SQLException;
// 提交事务
void commit() throws SQLException;
// 回滚事务
void rollback() throws SQLException;
// 关闭连接
void close() throws SQLException;
// 获取事务超时时间
Integer getTimeout() throws SQLException;
}
2.2 Transaction实现类
MyBatis提供了多种Transaction实现:
scss
Transaction (接口)
├── JdbcTransaction (JDBC事务)
├── ManagedTransaction (托管事务)
└── 自定义Transaction实现
JdbcTransaction是使用JDBC原生方式管理事务的实现:
java
public class JdbcTransaction implements Transaction {
protected Connection connection;
protected DataSource dataSource;
protected TransactionIsolationLevel level;
protected boolean autoCommit;
public JdbcTransaction(DataSource ds,
TransactionIsolationLevel desiredLevel,
boolean desiredAutoCommit) {
dataSource = ds;
level = desiredLevel;
autoCommit = desiredAutoCommit;
}
@Override
public Connection getConnection() throws SQLException {
if (connection == null) {
openConnection();
}
return connection;
}
@Override
public void commit() throws SQLException {
if (connection != null && !connection.getAutoCommit()) {
connection.commit();
}
}
@Override
public void rollback() throws SQLException {
if (connection != null && !connection.getAutoCommit()) {
connection.rollback();
}
}
@Override
public void close() throws SQLException {
if (connection != null) {
connection.close();
connection = null;
}
}
private void openConnection() throws SQLException {
connection = dataSource.getConnection();
if (level != null) {
connection.setTransactionIsolation(level.getLevel());
}
if (autoCommit != null
&& autoCommit != connection.getAutoCommit()) {
connection.setAutoCommit(autoCommit);
}
}
}
ManagedTransaction让容器来管理事务的生命周期:
java
public class ManagedTransaction implements Transaction {
private DataSource dataSource;
private TransactionIsolationLevel level;
private boolean closeConnection;
public ManagedTransaction(DataSource ds,
TransactionIsolationLevel level,
boolean closeConnection) {
this.dataSource = ds;
this.level = level;
this.closeConnection = closeConnection;
}
@Override
public Connection getConnection() throws SQLException {
if (connection == null) {
openConnection();
}
return connection;
}
@Override
public void commit() throws SQLException {
// 不做任何事,由容器管理提交
}
@Override
public void rollback() throws SQLException {
// 不做任何事,由容器管理回滚
}
@Override
public void close() throws SQLException {
if (closeConnection && connection != null) {
connection.close();
connection = null;
}
}
}
三、事务管理流程
完整的事务管理流程是确保数据一致性的关键。

3.1 事务生命周期
一个完整的事务生命周期包括以下阶段:
ini
// 1. 开启事务
SqlSession session = sqlSessionFactory.openSession();
try {
// 2. 执行数据库操作
User user = new User("张三", "zhangsan@example.com");
userMapper.insert(user);
Order order = new Order(user.getId(), "iPhone 15", 6999);
orderMapper.insert(order);
// 3. 提交事务
session.commit();
} catch (Exception e) {
// 4. 回滚事务
session.rollback();
throw e;
} finally {
// 5. 关闭会话
session.close();
}
3.2 自动提交与手动提交
MyBatis支持两种事务提交模式:
ini
// 自动提交模式:每条SQL自动提交
SqlSession session = sqlSessionFactory.openSession(true);
try {
User user = new User("张三", "zhangsan@example.com");
userMapper.insert(user);
// 无需手动提交,自动提交
} finally {
session.close();
}
// 手动提交模式:需要显式提交
SqlSession session = sqlSessionFactory.openSession(false);
try {
User user = new User("张三", "zhangsan@example.com");
userMapper.insert(user);
Order order = new Order(user.getId(), "iPhone 15", 6999);
orderMapper.insert(order);
// 多条SQL在同一事务中
session.commit(); // 显式提交
} catch (Exception e) {
session.rollback(); // 显式回滚
throw e;
} finally {
session.close();
}
3.3 Executor中的事务管理
Executor在执行SQL时会涉及到事务管理:
scss
public abstract class BaseExecutor implements Executor {
private Transaction transaction;
@Override
public int update(MappedStatement ms, Object parameter)
throws SQLException {
ErrorContext.instance().begin(ms.getId(),
ms.getSqlSource().getBoundSql(parameter));
try {
// 清空一级缓存
clearLocalCache();
// 执行更新操作
return doUpdate(ms, parameter);
} catch (SQLException e) {
throw ExceptionFactory.wrapException(
"Error updating database. Cause: " + e, e);
} finally {
ErrorContext.instance().end();
}
}
@Override
public void commit(boolean required) throws SQLException {
if (closed) {
throw new ExecutorException(
"Cannot commit, transaction is already closed");
}
// 清空一级缓存
clearLocalCache();
// 刷新批处理
flushStatements();
// 提交事务
if (required) {
transaction.commit();
}
}
@Override
public void rollback(boolean required) throws SQLException {
if (closed) {
throw new ExecutorException(
"Cannot rollback, transaction is already closed");
}
// 清空一级缓存
clearLocalCache();
// 刷新批处理
flushStatements(true);
// 回滚事务
if (required) {
transaction.rollback();
}
}
}
四、事务提交和回滚机制
事务的提交和回滚是保证数据一致性的核心机制。

4.1 事务提交流程
java
// SqlSession中的提交实现
@Override
public void commit() {
boolean commit = required;
try {
// 执行所有挂起的SQL语句
flushStatements();
if (commit) {
// 委托给Executor提交
executor.commit(isCommitOrRollbackRequired(false));
}
} catch (Exception e) {
throw ExceptionFactory.wrapException(
"Error committing transaction. Cause: " + e, e);
}
}
// Executor中的提交实现
@Override
public void commit(boolean required) throws SQLException {
if (closed) {
throw new ExecutorException(
"Cannot commit, transaction is already closed");
}
if (required) {
// 清空一级缓存
clearLocalCache();
// 刷新批处理
flushStatements();
// 提交数据库事务
transaction.commit();
}
}
4.2 事务回滚流程
java
// SqlSession中的回滚实现
@Override
public void rollback() {
try {
// 执行所有挂起的SQL语句
flushStatements(true);
// 委托给Executor回滚
executor.rollback(isCommitOrRollbackRequired(true));
} catch (Exception e) {
throw ExceptionFactory.wrapException(
"Error rolling back transaction. Cause: " + e, e);
}
}
// Executor中的回滚实现
@Override
public void rollback(boolean required) throws SQLException {
if (closed) {
throw new ExecutorException(
"Cannot rollback, transaction is already closed");
}
if (required) {
// 清空一级缓存
clearLocalCache();
// 刷新批处理
flushStatements(true);
// 回滚数据库事务
transaction.rollback();
}
}
4.3 回滚触发条件
以下情况会触发事务回滚:
ini
try {
userMapper.insert(user);
orderMapper.insert(order);
session.commit();
} catch (Exception e) {
session.rollback();
throw e;
}
if (!isValid(order)) {
session.rollback();
return;
}
session.commit();
SqlSession session = sqlSessionFactory.openSession(
ExecutorType.BATCH);
try {
List<User> users = getBatchUsers();
for (User user : users) {
userMapper.insert(user);
}
session.commit();
} catch (Exception e) {
session.rollback();
throw e;
} finally {
session.close();
}
4.4 事务隔离级别
MyBatis支持标准的JDBC事务隔离级别:
scss
public enum IsolationLevel {
NONE(Connection.TRANSACTION_NONE),
READ_COMMITTED(Connection.TRANSACTION_READ_COMMITTED),
READ_UNCOMMITTED(Connection.TRANSACTION_READ_UNCOMMITTED),
REPEATABLE_READ(Connection.TRANSACTION_REPEATABLE_READ),
SERIALIZABLE(Connection.TRANSACTION_SERIALIZABLE);
public int getLevel() {
return level;
}
}
配置方式:
xml
<!-- 在mybatis-config.xml中配置 -->
<settings>
<setting name="defaultTransactionIsolationLevel"
value="READ_COMMITTED"/>
</settings>
<!-- 在DataSource中配置 -->
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
<!-- 设置默认隔离级别 -->
<property name="defaultTransactionIsolationLevel"
value="2"/> <!-- READ_COMMITTED -->
</dataSource>
五、与Spring框架集成
在实际项目中,MyBatis通常与Spring集成,由Spring统一管理事务。

5.1 Spring事务配置
xml
<!-- 配置事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 配置事务通知 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="select*" read-only="true"/>
<tx:method name="get*" read-only="true"/>
<tx:method name="query*" read-only="true"/>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!-- 配置事务切面 -->
<aop:config>
<aop:pointcut id="servicePointcut"
expression="execution(* com.example.service.*.*(..))"/>
<aop:advisor advice-ref="txAdvice"
pointcut-ref="servicePointcut"/>
</aop:config>
@Configuration
@EnableTransactionManagement
public class MyBatisConfig {
@Bean
public DataSourceTransactionManager transactionManager(
DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean
public SqlSessionFactoryBean sqlSessionFactory(
DataSource dataSource) throws Exception {
SqlSessionFactoryBean sessionFactory =
new SqlSessionFactoryBean();
sessionFactory.setDataSource(dataSource);
sessionFactory.setMapperLocations(
new PathMatchingResourcePatternResolver()
.getResources("classpath:mapper/*.xml"));
return sessionFactory;
}
@Bean
public MapperScannerConfigurer mapperScannerConfigurer() {
MapperScannerConfigurer scanner =
new MapperScannerConfigurer();
scanner.setBasePackage("com.example.mapper");
return scanner;
}
}
5.2 使用@Transactional注解
在Service层使用@Transactional注解:
typescript
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
@Autowired
private OrderMapper orderMapper;
// 默认事务管理
@Transactional
public void createUserWithOrder(User user, Order order) {
userMapper.insert(user);
orderMapper.insert(order);
}
// 只读事务
@Transactional(readOnly = true)
public User getUserById(Long id) {
return userMapper.selectById(id);
}
// 指定隔离级别
@Transactional(isolation = Isolation.READ_COMMITTED)
public void updateUser(User user) {
userMapper.update(user);
}
// 指定传播行为
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void logOperation(String operation) {
// 在新事务中执行
}
// 指定回滚异常
@Transactional(rollbackFor = {Exception.class})
public void transfer(Long fromId, Long toId, BigDecimal amount) {
userMapper.decrease(fromId, amount);
userMapper.increase(toId, amount);
}
// 不回滚特定异常
@Transactional(noRollbackFor = {BusinessException.class})
public void processWithBusinessException() {
// ...
}
// 超时设置
@Transactional(timeout = 30)
public void longRunningOperation() {
// ...
}
}
5.3 Spring事务传播行为
Spring支持多种事务传播行为:
| 传播行为 | 说明 | 使用场景 |
|---|---|---|
| REQUIRED(默认) | 如果当前存在事务,则加入否则创建新事务 | 大多数情况 |
| REQUIRES_NEW | 总是创建新事务挂起当前事务 | 日志记录审计 |
| SUPPORTS | 如果当前存在事务,则加入否则非事务执行 | 查询操作 |
| NOT_SUPPORTED | 总是非事务执行挂起当前事务 | 批量导入 |
| NEVER | 总是非事务执行如果存在事务则抛异常 | 不需要事务的操作 |
| MANDATORY | 必须在事务中执行否则抛异常 | 必须有事务的操作 |
| NESTED | 如果当前存在事务则嵌套执行 | 嵌套业务逻辑 |
5.4 集成示例
java
@Service
public class OrderService {
@Autowired
private UserService userService;
@Autowired
private OrderService orderService;
@Autowired
private PaymentService paymentService;
// 主流程:使用REQUIRED传播
@Transactional(propagation = Propagation.REQUIRED)
public void createOrder(Order order) {
// 1. 创建用户(加入当前事务)
userService.updateUserBalance(
order.getUserId(),
order.getAmount().negate());
// 2. 创建订单(加入当前事务)
orderMapper.insert(order);
// 3. 支付(加入当前事务)
paymentService.processPayment(order);
// 事务提交
}
// 支付服务:REQUIRES_NEW,独立事务
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void processPayment(Order order) {
// 在新事务中执行
paymentMapper.insert(order);
}
// 异常处理:自动回滚
@Transactional(rollbackFor = Exception.class)
public void transfer(Long fromId, Long toId,
BigDecimal amount) {
try {
userService.decrease(fromId, amount);
userService.increase(toId, amount);
// 成功:自动提交
} catch (Exception e) {
// 失败:自动回滚
throw e;
}
}
}
六、事务传播机制
事务传播定义了事务方法被调用时事务边界的行为。

6.1 传播行为详解
typescript
@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {
methodB(); // 加入methodA的事务
}
@Transactional(propagation = Propagation.REQUIRED)
public void methodB() {
// ...
}
@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {
methodB(); // methodB在新事务中执行
// methodA的事务被挂起
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void methodB() {
// 在独立事务中执行
}
@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {
methodB(); // methodB在嵌套事务中执行
// 如果methodB失败,只回滚methodB
}
@Transactional(propagation = Propagation.NESTED)
public void methodB() {
// 在嵌套事务中执行
}
@Service
public class TransactionalService {
@Autowired
private LogService logService;
@Autowired
private DataService dataService;
// 主事务
@Transactional(propagation = Propagation.REQUIRED)
public void businessOperation() {
try {
// 1. 业务操作(主事务)
dataService.insertData("业务数据");
// 2. 记录日志(独立事务)
logService.saveLog("操作日志");
// 3. 发送通知(独立事务)
logService.sendNotification("操作通知");
} catch (Exception e) {
// 业务失败,主事务回滚
// 但日志记录和通知不会回滚
// (因为使用了REQUIRES_NEW)
throw e;
}
}
}
@Service
public class LogService {
// 独立事务记录日志
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void saveLog(String message) {
// 在新事务中执行
// 无论主事务成功或失败,日志都会被记录
logMapper.insert(message);
}
// 独立事务发送通知
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void sendNotification(String message) {
// 在新事务中执行
notificationMapper.insert(message);
}
}
@Service
public class IsolationLevelService {
// 读已提交:允许不可重复读
@Transactional(isolation = Isolation.READ_COMMITTED)
public List<User> listUsers() {
return userMapper.selectAll();
}
// 可重复读:防止不可重复读和幻读
@Transactional(isolation = Isolation.REPEATABLE_READ)
public User getUserWithLock(Long id) {
return userMapper.selectByIdForUpdate(id);
}
// 串行化:最高隔离级别
@Transactional(isolation = Isolation.SERIALIZABLE)
public void criticalOperation() {
// 串行执行,完全隔离
}
}
七、最佳实践
事务传播定义了事务方法被调用时事务边界的行为。
7.1 事务边界划分
java
✅ 事务范围要小 - 事务尽可能短,减少锁竞争
✅ 事务放在Service层 - 不在DAO层管理事务
✅ 避免长事务 - 不要在事务中进行RPC、HTTP等外部调用
✅ 明确事务边界 - 使用@Transactional清晰标注事务范围要小 - 事务尽可能短,减少锁竞争
✅ 事务放在Service层 - 不在DAO层管理事务
✅ 避免长事务 - 不要在事务中进行RPC、HTTP等外部调用
✅ 明确事务边界 - 使用@Transactional清晰标注
7.2 性能优化建议
ini
1️⃣ 选择合适的隔离级别 - READ_COMMITTED通常足够
2️⃣ 避免事务中的外部调用 - 如网络请求、文件操作
3️⃣ 批量操作使用BatchExecutor - 提升批量操作性能
4️⃣ 合理使用只读事务 - 查询操作使用readOnly=true
7.3 常见问题解决
typescript
// 问题:异常被捕获,事务未回滚
@Transactional
public void process() {
try {
// 业务代码
} catch (Exception e) {
e.printStackTrace(); // 捕获异常,事务不回滚
}
}
//解决:要么抛出异常,要么手动回滚
@Transactional(rollbackFor = Exception.class)
public void process() {
// 业务代码
}
// 查询方法使用只读事务
@Transactional(readOnly = true)
public List<User> listUsers() {
return userMapper.selectAll();
}
//好处:
//告诉数据库这是只读操作
//数据库可以进行优化
//减少锁竞争
// 设置事务超时时间(单位:秒)
@Transactional(timeout = 30)
public void longRunningOperation() {
// 如果方法执行超过30秒,事务自动回滚
}
MyBatis的事务管理模块提供了灵活而强大的事务控制能力。
1️⃣ Transaction接口 - 定义事务的基本操作
2️⃣ JdbcTransaction - 使用JDBC原生方式管理事务
3️⃣ ManagedTransaction - 由容器管理事务生命周期
4️⃣ 事务提交和回滚 - 根据操作结果决定提交或回滚
5️⃣ 框架集成 - 与Spring等框架无缝集成