12.Spring声明式事务管理
- 使用 MyBatis-Spring 的其中一个主要原因是它允许 MyBatis 参与到 Spring 的事务管理中。
- 而不是给 MyBatis 创建一个新的专用事务管理器,MyBatis-Spring 借助了 Spring 中的 DataSourceTransactionManager 来实现事务管理。
- 一旦配置好了 Spring 的事务管理器,你就可以在 Spring 中按你平时的方式来配置事务。
- 并且支持 @Transactional 注解和 AOP 风格的配置。在事务处理期间,一个单独的
SqlSession
对象将会被创建和使用。当事务完成时,这个 session 会以合适的方式提交或回滚。 - 要开启 Spring 的事务处理功能,在 Spring 的配置文件中创建一个
DataSourceTransactionManager
对象:
测试事务代码:
- 事务的添加删除要么同时成功要么同时失败
public List<User> findAll() throws Exception {
User user=new User();
user.setAge(30);
user.setEmail("12121212@qq.com");
user.setPassword("111111");
user.setName("yanggoushen");
user.setId(5);
user.setGender(1);
user.setPhone("1212121212");
UserMapper mapper = getSqlSession().getMapper(UserMapper.class);
mapper.addUser(user);
mapper.deleteUser(5);
return mapper.findAll();
}
配置文件代码
- 配置声明式事务(需要关联数据库)
- 配置tx事务通知 需要指定给哪些方法添加事务
- 配置事务切入需要指定哪些类会被事务管理 需要引入事务tx和切入点
<!--配置声明式事务-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--结合AOP实现事务织入-->
<!--配置事务通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!--给哪些方法配置事务-->
<tx:attributes>
<tx:method name="add" propagation="REQUIRED"/>
<tx:method name="delete"/>
<tx:method name="update"/>
<tx:method name="find" read-only="true"/>
<!-- 对所有的方法都已默认的事务方式执行-->
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!--配置事务切入-->
<aop:config>
<!--这个包下的所有方法都会被事务管理-->
<aop:pointcut id="pointcut" expression="execution(* com.xuan.mapper.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"/>
</aop:config>
补充一下事务管理对方法条件限定的属性propagation
-
在声明式的事务处理中,要配置一个切面,其中就用到了propagation,表示打算对这些方法怎么使用事务,是用还是不用,其中propagation有七种配置,REQUIRED、SUPPORTS、MANDATORY、REQUIRES_NEW、NOT_SUPPORTED、NEVER、NESTED。默认是REQUIRED。
-
REQUIRED:**支持当前事务,如果当前没有事务,就新建一个事务。**这是最常见的选择。
-
SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。
-
MANDATORY:支持当前事务,如果当前没有事务,就抛出异常。
-
REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。
-
NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
-
NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
-
NESTED:支持当前事务,如果当前事务存在,则执行一个嵌套事务,如果当前没有事务,就新建一个事务。