Java EE应用的传统事务有两种策略:全局事务和局部事务。全局事务由应用服务器管理,需要底层服务器的JTA支持。局部事务和底层所采用的持久化技术有关,当采用JDBC持久化技术时,需要使用Connection对象来操作事务;而采用Hibernate持久化技术时,需要使用Session对象来操作事务。
spring事务策略是通过PlatformTransactionManager接口体现的,该接口是spring事务策略的核心。
PlatformTransactionManager接口有许多不同的实现类,应用程序面向与平台无关的接口编程,当底层采用不同的持久层技术时,系统只需要使用不同的PlatformTransactionManager实现类即可,而这种切换通常由spring容器负责管理,应用程序既无须与具体的事务API耦合,也无须与特定实现类耦合,从而将应用和持久化技术、事务API彻底分离。
spring的事务机制是一种典型的策略模式,PlatformTransactionManager代表事务管理接口,但它并不知道底层到底如何管理事务,它只要求事务管理需要提供开始事务(getTransaction())、提交事务(commit())和回滚事务(rollback())三个方法。
在PlatformTransactionManager接口内,包含一个getTransaction(TransactionDefinition definition)方法,该方法根据参数返回一个TransactionStatus对象。TransactionStatus对象表示一个事务,被关联在当前执行的线程上。返回的事务可能是一个新的事务,也可能是一个已经存在的事务对象。
TransactionDefinition接口定义了一个事务规则,该接口必须指定如下几个属性值:
- 事务隔离:当前事务和其他事务的隔离程度。
- 事务传播:通常,在事务中执行的代码都会在当前事务中运行。但是,如果一个事务上下文已经存在,有几个选项可指定该事务性方法的执行行为。
- 事务超时:事务在超时前能运行多久,也就是事务的最长持续时间。
- 只读状态:只读事务不修改任何数据。
在spring容器中配置PlatformTransactionManager Bean时,必须针对不同的环境提供不同的实现类。
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destory-method="close" p:driverClass="com.mysql.jdbc.Driver" p:jdbcUrl="jdbc:mysql://localhost:3306/" p:user="root" p:password="0408" p:maxPoolSize="40" p:minPoolSize="2" p:initialPoolSize="2" p:maxIdleTime="30"/>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" p:dataSource-ref="dataSource"/>
spring提供了如下两种事务管理方式:
- 编程式事务管理:即使使用spring的编程式事务,程序也可直接获取容器中的transactionManager Bean,该Bean总是PlatformTransactionManager的实例,所以可以通过该接口提供的三个方法来开始事务、提交事务和回滚事务。
- 声明式事务:无须再Java程序中书写任何事务操作的代码,而是通过在XML文件中为业务组件配置事务代理(AOP代理的一种),AOP为事务代理所织入的增强处理也由Spring提供—在目标方法执行之前,织入开始事务;在目标方法执行之后,织入结束事务。
1.使用XML配置事务策略
tx:命名空间来配置事务管理,<tx:advice.../>
元素来配置事务增强处理。一旦使用过了该元素配置了事务增强处理,就可直接使用<aop:advisor.../>
元素启用自动代理了。
配置<tx:advice.../>
元素时除了需要transaction-manager属性指定事务管理其之外,还需要配置一个<attributes.../>
子元素,该子元素里又可包含多个<method.../>
子元素。
实际上每个<method.../>
子元素都为一批方法指定了所需的事务定义,包括事务传播属性、事务隔离属性、事务超时属性、只读事务、对指定异常回滚、对指定异常不回滚等。可指定如下属性:
- name:必选属性,与该事务语义关联的方法名。
- propagation:指定事务的传播行为。
- isolation:指定事务的隔离级别。
- timeout:指定事务超时的时间,指定-1意味着不超时。
- read-only:指定事务是否只读。
- rollback-for:指定触发事务回滚的异常类(应使用全限定类名)。
- no-rollback-for:指定不触发事务回滚的异常类(应使用全限定类名)。
当采用<aop:advisor.../>
元素将Advice和切入点绑定时,实际上是由spring体用的Bean后处理器完成的。spring提供了BeanNameAutoProxyCreator、DefaultAdvisorAutoProxyCreator两个Bean后处理器。
在默认情况下,只有当方法引发运行时异常和unchecked异常时,spring事务机制才会自动回滚事务。
2.使用@Transactional
使用@Transactional修饰Bean类时,则表明这些事务设置对整个Bean类起作用;如果修饰某个方法时,则表明这些事务设置只对该方法有效。
使用@Transactional时可指定如下属性:
- isolation:用于指定事务的隔离级别。
- noRollbackFor:指定遇到特定异常时强制不回滚事务。
- noRollbackForClassName:指定遇到特定的多个异常时强制不回滚事务。
- propagation:指定事务传播行为。
- readOnly:指定事务是否只读。
- rollbackFor:指定遇到特定异常时强制回滚事务。
- rollbackForClassName:指定遇到特定的多个异常时强制回滚事务。
- timeout:指定事务的超时时长。
需要在spring配置文件中加入 :
<tx:annotation-driven transaction-manager="transactionManager"/>