Spring如何管理事务的
Spring事务管理主要包括3个接口,事务管理器,事务定义信息,事务具体运行状态:
1)、PlatformTransactionManager:事务管理器,主要用于平台相关事务的管理。主要包括三个方法:①、commit:事务提交。②、rollback:事务回滚。③、getTransaction:获取事务状态。
2)、TransacitonDefinition:事务定义信息,用来定义事务相关属性,给事务管理器PlatformTransactionManager使用这个接口有下面四个主要方法:①、getIsolationLevel:获取隔离级别。②、getPropagationBehavior:获取传播行为。③、getTimeout获取超时时间。④、isReadOnly:是否只读(保存、更新、删除时属性变为false–可读写,查询时为true–只读)事务管理器能够根据这个返回值进行优化,这些事务的配置信息,都可以通过配置文件进行配置。
3)、TransationStatus:事务具体运行状态,事务管理过程中,每个时间点事务的状态信息。例如:①、hasSavepoint():返回这个事务内部是否包含一个保存点。②、isCompleted():返回该事务是否已完成,也就是说,是否已经提交或回滚。③、isNewTransaction():判断当前事务是否是一个新事务。
传播行为和隔离级别
1> 事务注解方式: @Transactional
标注在类前:标示类中所有方法都进行事务处理
标注在接口、实现类的方法前:标示方法进行事务处理
2> 事务传播行为介绍:
@Transactional(propagation=Propagation.REQUIRED)
支持当前事务,如果当前没有事务,就新建一个事务。
如果其他bean调用这个方法,在其他bean中声明事务,就不再起新的事务。
如果其他bean调用这个方法,如果其他bean没有声明事务,就不再起新的事务。就新建一个事务。两个bean的任何地方出现异常,事务都会被回滚。
@Transactional(propagation=Propagation.SUPPORTS)
如果其他bean调用这个方法,在其他bean中声明事务,那就用事务。如果其他bean没有声明事务,那就不用事务
@Transactional(propagation=Propagation.MANDATORY)
必须在一个已有的事务中执行,否则抛出异常
@Transactional(propagation=Propagation.REQUIRES_NEW)
不管是否存在事务,都创建一个新的事务,原来的挂起,新的执行完毕,继续执行老的事务.存在两个不同的事务,各自回滚各自的
@Transactional(propagation=Propagation.NOT_SUPPORTED)
以非事务方式执行当前操作,如果当前存在事务,就把事务挂起来。
3> 事务超时设置:
@Transactional(timeout=30) //默认是30秒
4> 事务隔离级别:
@Transactional(isolation = Isolation.READ_UNCOMMITTED)
读取未提交数据(会出现脏读, 不可重复读),基本不使用
@Transactional(isolation = Isolation.READ_COMMITTED)(SQLSERVER默认)
读取已提交数据(会出现不可重复读和幻读)
@Transactional(isolation = Isolation.REPEATABLE_READ)
可重复读(会出现幻读)
@Transactional(isolation = Isolation.SERIALIZABLE)
串行化
脏读 : 一个事务读取到另一事务未提交的更新数据
不可重复读 : 在同一事务中, 多次读取同一数据返回的结果有所不同, 换句话说, 后续读取可以读到另一事务已提交的更新数据。相反,”可重复读”在同一事务中多次读取数据时,能够保证所读数据一样,也就是后续读取不能读到另一事务已提交的更新数据
幻读 : 一个事务读到另一个事务已提交的insert数据
Transactional的配置使用
配置事务的方法有两种:
1)、基于注解配置
步骤一、在Spring配置文件中引入命名空间
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
步骤二、xml配置文件中,添加事务管理器bean配置
<!-- 事务管理器配置,单数据源事务 -->
<bean id="pkgouTransactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="pkGouDataSource" />
</bean>
<!-- 使用注解定义事务 -->
<tx:annotation-driven transaction-manager="pkgouTransactionManager" />
步骤三、在使用事务的方法或者类上添加 @Transactional(“pkgouTransactionManager”)注解
1)、基于XML的事务配置。
<!-- 事务管理器配置,多数据源事务,根据service接口上的注解来决定取哪个数据源 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="dataSource" class="com.jd.bdp.buffalo.manager.web.datasource.DynamicDataSource">
<property name="targetDataSources">
<map key-type="java.lang.String">
<entry key="slave" value-ref="slaveDataSource"/>
<entry key="master" value-ref="masterDataSource"/>
</map>
</property>
<property name="defaultTargetDataSource" ref="masterDataSource"/>
</bean>
<!-- transaction manager, use JtaTransactionManager for global tx -->
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="dataSourceAspect" class="com.manager.web.aspect.DataSourceAspect"/>
<aop:config proxy-target-class="true">
<aop:aspect id="dataSourceAspect" ref="dataSourceAspect" order="2">
<aop:pointcut id="tx" expression="execution(* com.manager.service..*.*(..)) "/>
<aop:around method="processDataSource" pointcut-ref="tx"/>
</aop:aspect>
</aop:config>