spring的事务管理
引言
在软件中,要么全有(全部发生)要么全无(全部都没发生)的操作称为事务!
spring的事务管理与spring的缓存机制一样,都是基于spring的AOP,因此,spring的事务管理与spring的缓存机制在配置上是非常相似的。spring的事务管理包括编程式事务、基于xml配置式事务、注解驱动式事务。下面分别介绍这三种事务管理。
在介绍spring事务管理之前,有必要对事务的一些参数作出说明
1.spring事务参数
spring事务参数在org.springframework.transaction.TransactionDefinition接口中作出了常量定义。
1.1传播行为(PROPAGATION)
传播行为 | 意义 |
PROPAGATION_MANDATORY | 表示该方法必须运行在一个事务中。如果当前没有事务正在发生,将抛出一个异常 |
PROPAGATION_NESTED | 表示如果当前正有一个事务在进行中,则该方法应当运行在一个嵌套式事务中。被嵌套的事务可以独立于封装事务进行提交或回滚。如果封装事务不存在,行为就像PROPAGATION_REQUIRED一样。请注意各厂商对于这种传播行为的支持是参差不齐的。请参考资源管理器的文档,确定它们是否支持嵌套式事务 |
PROPAGATION_NEVER | 表示当前的方法不应该在一个事务性上下文中运行。如果当前正有一个事务在运行,则会抛出一个异常 |
PROPAGATION_NOT_SUPPORTED | 表示该方法不应该在一个事务中运行。如果一个现有的事务正在进行中,它将在该方法的运行期间被挂起 |
PROPAGATION_REQUIRED | 表示当前方法必须在一个事务中运行。如果一个现有的事务正在进行中,该方法将会在那个事务中运行。否则的话,就要开始一个新的事务 |
PROPAGATION_REQUIREDS_NEW | 表示当前方法必须在它自己的事务里运行。一个新的事务将被启动,而且如果有一个现有事务正在运行的话,则将在这个方法运行期间被挂起。如果正在使用JTATransactionManager,则需要访问TransactionManager |
PROPAGATION_SUPPORTS | 表示当前方法不需要事务性上下文,但是如果有一个事务已经在运行的话,它也可以在这个事务里运行 |
1.2事务隔离级别
隔离级别 | 含义 |
ISOLATION_DEFAULT | 使用后端数据库默认的隔离级别 |
ISOLATION_READ_UNCOMMITTED | 允许读取尚未提交的更改。可能导致脏读、幻读或不可重复读 |
ISOLATION_READ_COMMITED | 允许从已经提交的并发事务读取。可防止脏读、幻读或不可重复读 |
ISOLATION_REPEATABLE_READ | 对相同字段的多次读取的结果是一致的,除非数据被当前事务本身改变。可防止脏读和不可重复读,但幻读仍可发生 |
ISOLATION_SERIALIZABLE | 完全服从ACID的隔离级别,确保不发生脏读、不可重复读和幻读。这在所有隔离级别中也是最慢的,因为它通常是通过完全锁定当前事务所涉及的数据表来完成的。 |
1.3只读
如果一个事务只对后端数据库执行读操作,那么该数据库就可能可以利用那个事务的只读特性,采取某些优化措施。由于只读的优化措施是在一个事务启动时由后端数据库实施的,因此,只有对于那些具有可能启动一个新事务的传播行为(PROPAGATION_REQUIRED,PROPAGATION_REQUIREDS_NEW,PROPAGATION_NESTED)的方法来说,将事务声明为只读才有意义。
1.4事务超时
声明一个事务,在特定的秒数之后自动回滚,而不必等它自己结束。
1.5回滚规则
回滚规则定义哪些异常会引起回滚,哪些不引起。在默认设置下,事务只在出现运行异常(runtime exception)时回滚,而在出现受阻异常(checked exception)时不回滚。不过,也可以在回滚规则中声明一个事务在出现特定的受阻异常时像运行时异常一样回滚。同样,也可以声明一个事务在出现特定的异常时不回滚,包括运行时异常。
2.spring的事务管理器
spring中的事务管理器它就是AOP中的Advice!或者可以这样去理解它!事务管理器中包含了事务管理的功能代码。
spring提供了多个基于特定持久平台的事务管理器,所有这些事务管理器都实现了org.springframework.transaction.PlatformTransactionManager。
下面是jdbc的事务管理器的配置(其它持久平台的事务管理器的配置很相似):
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean>
3.基于XML方式配置事务
3.1代理事务
<bean id="rantService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <property name="target" ref="rantServiceTarget" /> <property name="proxyInterfaces" value="com.roadrantz.service.RantService" /> <property name="transactionManager" ref="transactionManager"></property> <property name="transactionAttributes"> <props> <prop key="add*">PROPAGATION_REQUIRED</prop> <prop key="*">PROPAGATION_SUPPORTS,readOnly</prop> </props> </property> </bean>
transactionAttributes中的配置按如下的顺序:
PROPAGATION,ISOLATION(可选),readOnly(可选),-Exception(可选),+Exception(可选)
3.2 spring2.0事务的简化配置
<tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="add*" propagation="REQUIRED" /> <tx:method name="*" propagation="SUPPORTS" read-only="true" /> </tx:attributes> </tx:advice> <aop:config> <aop:advisor advice-ref="txAdvice" pointcut="execution(* *..RantService.*(..))" /> </aop:config>
4.注解驱动式事务配置
- 添加如下配置
<tx:annotation-driven transaction-manager="transactionManager"/>
- 在相应的类的类级别或方法级别上添加@Transactional注解
@Transactional(propagation=Propagation.SUPPORTS,readOnly=true) public class RantServiceImpl implements RantService{ ... @Transactional(propagation=Propagation.REQUIRED,readOnly=false) public void addRant(Rant rant){} }
5.编程式事务管理
(略)