欢迎访问:我的个人网站
Spring 事务管理
事务可以理解为与数据库相关的一组操作,要么全部执行,要么全部不执行。
Spring提供两种事务管理模式:
- 编程式的实现。
- 声明式的实现,其中又包含注解实现以及配置文件实现。
Spring事务管理的几个高层接口有以下几个:PlatformTransactionManager事务管理器,事务定义信息TransactionDefinition事务定义信息,TransactionStatus事务状态。针对接口PlatformTransactionManager,有不同的实现类,这些实现类可以根据不同的持久层框架进行选择使用:
- DataSourceTransactionManage: 使用JDBCTemplate / iBatis / Mybatis 进行持久化工作。
- HibernateTransactionManage: 使用Hibernate5.0+的版本使用这个实现类进行事务处理。
- JpaTransactionManage: 使用JPA进行持久化时候使用。
- JdoTransactionManage: 使用Jdo进行持久化时候使用。
- JtaTransactionManage: 使用一个JTA实现来管理事务,在一个事务跨越了多个资源的时候,必须使用。
事件模拟
模拟一个事件以演示事务的使用,整体流程如下:service处理转账逻辑,调用DAO进行数据持久化服务。service在执行的过程中主动引发一个异常,转账逻辑将不完整,发生错误。
1.DAO层建立一个转账类并在配置文件进行配置,内部包含一个转账方法:
@Repository
public class Dao {
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate){
this.jdbcTemplate = jdbcTemplate;
}
public void fun(String name, Integer salay){
jdbcTemplate.update("update t1 set salary = ? where name = ?", salay, name);
}
}
2.创建Service类, 在配置文件进行配置,进行操作,调用DAO中的方法进行处理:
public class Service {
private Dao dao;
public void setDao(Dao dao){
this.dao = dao;
}
public void service(){
dao.fun("KK",100);
int a = 1/0;
dao.fun("MM", 150);
}
}
3.在配置文件中针对以上内容进行处理:
<!--组件扫描-->
<context:component-scan base-package="com"></context:component-scan>
<!--配置数据源-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="root"/>
<property name="password" value="111"/>
<property name="jdbcUrl" value="jdbc:mysql:///test"/>
<property name="driverClass" value="com.mysql.jdbc.Driver"/>
</bean>
<!--配置JdbcTemplate对象-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--配置DAO注入JdbcTemplate-->
<bean id="dao" class="com.bestbigkk.Dao">
<property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>
<!--配置Service并注入DAO-->
<bean id="service" class="com.bestbigkk.Service">
<property name="dao" ref="dao"/>
</bean>
调用Service方法进行处理之后,由于自动的引发了异常,所以在设置了KK的 余额之后,MM的余额无法被正常修改,造成业务逻辑的错误。所以要使用事务处理,在一项操作未正确完成的时候,可以进行回滚操作。
声明式的事务管理(Xml)
- 创建事务管理器。
- 根据事务管理器创建事务增强器。
- 将创建的事务增强器应用到创建的切入点上面。
1.创建事务管理器。根据具体使用的DAO对象或者框架进行选择,这里使用的是JdbcTemplate,所以使用DataSourceTransactionManager对象, 实际情况下,根据需要进行选择创建。
<bean id="DataSourceTransactionManage" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
2.配置事务增强器:
- transaction-manager: 指定使用哪个事务管理器。
- id: 该事务增强器的名称。
- name: 指定要增强哪些方法,支持正则表达式。
<tx:advice transaction-manager="DataSourceTransactionManage" id="transactionInterceptor">
<tx:attributes>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
3.配置切面,将配置的事务增强器应用到所建立的切入点上:
- 1.配置切入点
- 2.配置应用到切入点的事务增强器
<aop:config>
<aop:pointcut id="point" expression="execution(* com.bestbigkk.Service.*(..))"/>
<aop:advisor advice-ref="transactionInterceptor" pointcut-ref="point"/>
</aop:config>
完整Xml配置文件:
<!--配置数据源-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="root"/>
<property name="password" value="111"/>
<property name="jdbcUrl" value="jdbc:mysql:///test"/>
<property name="driverClass" value="com.mysql.jdbc.Driver"/>
</bean>
<!--配置JdbcTemplate对象-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--配置DAO注入JdbcTemplate-->
<bean id="dao" class="com.bestbigkk.Dao">
<property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>
<!--配置Service并注入DAO-->
<bean id="service" class="com.bestbigkk.Service">
<property name="dao" ref="dao"/>
</bean>
<!--配置事务管理器,这里使用的是JdbcTemplate,所以使用DataSourceTransactionManager对象, 实际情况下,根据需要进行选择创建。-->
<bean id="DataSourceTransactionManage" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<tx:advice transaction-manager="DataSourceTransactionManage" id="transactionInterceptor">
<tx:attributes>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="point" expression="execution(* com.bestbigkk.Service.*(..))"/>
<aop:advisor advice-ref="transactionInterceptor" pointcut-ref="point"/>
</aop:config>
此时再运行上述代码,在出现异常之后,数据会自动回滚到之前的状态以保证业务逻辑的正常处理。
声明式的事务管理(注解)
该方法相较于Xml配置而言很简单,大体分为三个步骤:
- 配置事务管理器。
- 配置注解。
- 使用注解。
1.配置事务管理器,根据需要进行选择,并注入数据源:
<!--配置事务管理器-->
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
2.配置注解,选择要使用的事务管理器:
<tx:annotation-driven transaction-manager="transactionManager"/>
3.使用注解,在要进行事务控制的方法所属类上使用 @Transactional 注解即可:
@Transactional
public class Service {
//...
}