声明式事务
Spring和MyBatis整合之后,默认会关闭事务,开启自动提交。因此事务需要手动打开。
一个使用 MyBatis-Spring 的其中一个主要原因是它允许 MyBatis 参与到 Spring 的事务管理中。而不是给 MyBatis 创建一个新的专用事务管理器,MyBatis-Spring 借助了 Spring 中的 DataSourceTransactionManager
来实现事务管理。
一旦配置好了 Spring 的事务管理器,你就可以在 Spring 中按你平时的方式来配置事务。并且支持 @Transactional
注解和 AOP 风格的配置。在事务处理期间,一个单独的 SqlSession
对象将会被创建和使用。当事务完成时,这个 session 会以合适的方式提交或回滚。
- 声明式事务:AOP
- 编程式事务:需要在代码中,进行事务的管理。
1. 使用方法
这里直接在与MyBatis整合的第二种方式上进行修改。
详见这里。
mybatis配置文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <!--configuration核心配置文件--> <configuration> <typeAliases> <typeAlias type="org.gs.pojo.User" alias="user"/> </typeAliases> <mappers> <mapper resource="org/gs/mapper/UserMapper.xml" /> </mappers> </configuration>
spring配置文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx https://www.springframework.org/schema/tx/spring-tx.xsd"> <!--从db.properties获取db配置信息--> <context:property-placeholder location="db.properties"/> <!--将db配置信息配置到spring的数据源中--> <!-- 这里也可以选择其他数据源,如 c3p0 dbcp druid--> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </bean> <!--配置SqlSessionFactory--> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!--将数据源内容注入--> <property name="dataSource" ref="dataSource"/> <!--可以携带mybatis原有的配置文件,一般用来指定别名--> <property name="configLocation" value="classpath:mybatis-config.xml"/> <!--此处也可以映射文件--> <!--其实mybatis配置文件中的配置都可以在这里完成--> <!--<property name="mapperLocations" value="classpath:org/gs/mapper/UserMapper.xml"/>--> </bean> <!--配置mapper实现类,注入SqlSession--> <bean id="userMapper" class="org.gs.mapper.UserMapperImpl"> <property name="sqlSessionFactory" ref="sqlSessionFactory"/> </bean> <!--要开启 Spring 的事务处理功能,在 Spring 的配置文件中创建一个 DataSourceTransactionManager 对象--> <bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <constructor-arg name="dataSource" ref="dataSource"/> </bean> <!--配置事务的切面--> <tx:advice id="interceptor" transaction-manager="dataSourceTransactionManager"> <!--给哪些方法配置事务--> <tx:attributes> <tx:method name="add"/> <tx:method name="update" propagation="REQUIRED"/> <tx:method name="query" read-only="true"/> <!--可以使用通配符--> <!--<tx:method name="*" propagation="REQUIRED"/>--> </tx:attributes> </tx:advice> <aop:config> <aop:pointcut id="pointcut" expression="execution(* org.gs.mapper.*.*(..))"/> <aop:advisor advice-ref="interceptor" pointcut-ref="pointcut"/> </aop:config> </beans>
完成以上步骤,就可以通过Spring给对应的mapper上指定的方法织入事务。
2. 相关属性
2.1. 配置事务的传播特性 propagation
- REQUIRED:支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。(默认)
- SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。
- MANDATORY:支持当前事务,如果当前没有事务,就抛出异常。
- REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。
- NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
- NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
- NESTED:支持当前事务,如果当前事务存在,则执行一个嵌套事务,如果当前没有事务,就新建一个事务。
3. 注意点
@Transactional
只能回滚RuntimeException
以及其下子类抛出的异常,而不能回滚Exception
抛出的异常。- 如果需要支持回滚
Exception
异常需要加@Transactional(rollbackFor = Exception.class)
,建议添加。 - 如果方法不是public所修饰,则不会对Bean进行代理对象的创建以及代理方法的调用。
- Spring的事务通过代理对象来调用并提交/回滚。通过对类内部的方法调用并没有走代理方法调用,最终导致事务失效。