22. MyBatis如何处理事务?与Spring事务管理如何集成?
大约 4 分钟
MyBatis本身并不直接管理事务,它依赖于外部的事务管理机制,通常通过JDBC的Connection
对象来管理事务。MyBatis中的事务处理主要包括手动管理事务和与Spring事务管理的集成。
1. 手动管理事务
在不使用Spring的情况下,MyBatis的事务管理需要通过手动控制SqlSession
来实现。以下是手动管理事务的步骤:
- 开启事务:
- 使用
SqlSession
对象时,通常会通过SqlSessionFactory
来获取一个新的SqlSession
实例。 - 事务默认是自动提交的(
autoCommit
为true
),可以通过SqlSessionFactory.openSession(false)
来手动控制事务。
- 使用
- 提交事务:
- 在执行完所有的SQL操作后,手动调用
SqlSession.commit()
来提交事务。
- 在执行完所有的SQL操作后,手动调用
- 回滚事务:
- 如果在事务操作过程中发生异常,可以调用
SqlSession.rollback()
来回滚事务。
- 如果在事务操作过程中发生异常,可以调用
- 关闭
SqlSession
:- 在完成事务处理后,必须关闭
SqlSession
以释放数据库连接资源。
- 在完成事务处理后,必须关闭
SqlSessionFactory sqlSessionFactory = ...; // 获取 SqlSessionFactory
SqlSession sqlSession = null;
try {
sqlSession = sqlSessionFactory.openSession(); // 关闭自动提交
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// 执行插入操作
mapper.insertUser(new User("John", "john@example.com"));
sqlSession.commit(); // 手动提交事务
} catch (Exception e) {
if (sqlSession != null) {
sqlSession.rollback(); // 发生异常时回滚事务
}
e.printStackTrace();
} finally {
if (sqlSession != null) {
sqlSession.close(); // 关闭 SqlSession
}
}
与Spring事务管理的集成
在大多数实际应用中,MyBatis通常与Spring框架集成使用,Spring提供了强大的声明式事务管理机制,可以简化事务管理工作。
1. Spring声明式事务管理
Spring提供了基于AOP(面向切面编程)的声明式事务管理机制,只需在业务方法或类上加上@Transactional
注解即可。Spring会自动管理事务的开启、提交和回滚,简化了开发者的工作。
1.1 配置Spring与MyBatis的集成
假设已经通过Spring集成了MyBatis,可以通过以下步骤配置Spring的事务管理:
配置数据源:
- 配置数据库连接池,如HikariCP、DBCP等。
<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource"> <property name="driverClassName" value="com.mysql.cj.jdbc.Driver" /> <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/mydb" /> <property name="username" value="root" /> <property name="password" value="password" /> </bean>
配置
SqlSessionFactory
:- 配置MyBatis的
SqlSessionFactoryBean
。
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="mapperLocations" value="classpath:mapper/*.xml" /> </bean>
- 配置MyBatis的
配置事务管理器:
- 使用Spring的
DataSourceTransactionManager
来管理事务。
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean>
- 使用Spring的
启用事务管理:
- 在Spring配置中启用注解驱动的事务管理。
<tx:annotation-driven transaction-manager="transactionManager" />
1.2 使用@Transactional
注解
在业务层或Service层,可以使用@Transactional
注解来声明需要进行事务管理的方法或类。
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
@Transactional // 开启事务管理
public void createUser(User user) {
userMapper.insertUser(user);
// 其他可能会抛出异常的业务逻辑
}
}
@Transactional
:标注在方法或类上,表示该方法或类中的所有公共方法都在事务中执行。Spring会根据方法的执行情况自动提交或回滚事务。- 事务传播属性:可以通过配置
@Transactional
的propagation
属性控制事务的传播行为(如REQUIRED
、REQUIRES_NEW
等)。 - 异常回滚:默认情况下,Spring会对
RuntimeException
或更严重的异常进行回滚。可以通过配置rollbackFor
或noRollbackFor
属性自定义回滚行为。
2. Spring与MyBatis事务管理集成的优势
- 简化开发:通过声明式事务管理,开发者无需手动编写事务管理代码,只需在类或方法上添加
@Transactional
注解即可。 - 可配置性强:Spring的事务管理具有高度的可配置性,可以通过各种事务属性(如传播属性、隔离级别、超时时间等)来满足复杂的业务需求。
- 统一管理:Spring的事务管理可以统一管理应用程序中的所有事务,无论是MyBatis、JPA、JDBC还是其他数据访问技术。
3. 事务管理注意事项
- 嵌套事务:在嵌套的事务调用中,Spring默认使用传播属性
REQUIRED
,即嵌套方法会加入当前事务中。如果希望嵌套方法开启新事务,可以使用REQUIRES_NEW
传播属性。 - 事务隔离级别:可以通过
@Transactional
注解的isolation
属性设置事务的隔离级别(如READ_COMMITTED
、SERIALIZABLE
等),以控制并发访问的行为。 - 事务回滚:确保在需要回滚的异常情况下正确配置
rollbackFor
属性,以避免事务提交带来的数据不一致性。
总结
MyBatis本身不管理事务,通常通过JDBC的Connection
对象来管理事务。在Spring环境中,MyBatis通常与Spring的声明式事务管理机制集成,通过@Transactional
注解来简化事务管理工作。Spring提供了强大的事务管理功能,支持多种事务传播属性、隔离级别和回滚规则,能够有效地管理复杂的事务场景。