最近在调项目的性能,又重新过了温习了一下spring事务的相关内容,做如下总结:
一、声明式spring事务的控制
Spring 的声明式事务管理在底层是建立在 AOP 的基础之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。
1、spring事务配置方式
声明式spring事务的配置方式有三种:
1)使用TransactionInterceptor类来实施声明式事务管理功能,涉及到的spring类有org.springframework.transaction.interceptor.TransactionInterceptor、org.springframework.aop.framework.ProxyFactoryBean
2) 基于TransactionProxy... 的声明式事务管理,1)中的声明式事务在配置过程中需要的配置文件多,而且需要针对每一个目标对象配置一个ProxyFactoryBean。为缓解这个问题,spring将TransactionInterceptor和ProxyFacotryBean的配置合二为一,为我们提供了TransactionProxyFactoryBean用于事务的配置,配置较先前的简单很多。
3) 基于 <tx>命名空间的声明式事务管理,使声明式事务变的更加简单与灵活。
4)基于 @Transactional 的声明式事务管理,@Transactional可以作用于接口、接口方法、类及类方法上。当作用于类上时,该类的所有public 方法将都具有该类型的事务属性,同时,我们也可以在方法级别使用该标注来覆盖类级别的定义。由于在接口方法上使用该注解只有在使用基于接口的代理时才会生效,所以spring小组建议不要将注解使用在接口或接口的方法上。同时 @Transactional 注解应该只被应用到 public 方法上,在protected、private或者默认可见性的方法上使用会被spring忽略。
1)、2)方式配置繁琐,现在值针对3)、4)进行说明
基于<tx>的事务管理示例配置文件
<bean id="transactionManager"class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <propertyname="sessionFactory" ref="sessionFactory" /> </bean> <aop:config> <aop:advisoradvice-ref="txAdvice" pointcut="execution(**..service.*Manager.*(..))" order="100" /> </aop:config> <!-- 如果事务管理Bean的名字取值为"transactionManager",则可以省略transaction-manager属性,其属性的默认值为"transactionManager" <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:methodname="*" rollback-for="Throwable"propagation="REQUIRED"/> </tx:attributes> </tx:advice>
基于 @Transactional 的事务管理示例配置文件
@Transactional(propagation =Propagation.REQUIRED) public void save(CircleModel model) { ..... }
Sping 使用 BeanPostProcessor 来处理 Bean 中的标注,所以我们需要在spring配置文件中开启注解事务控制,需要添加如下配置项:
<!-- transaction-manager 属性的默认值是 transactionManager,如果事务管理器 Bean 的名字即为该值,则可以省略 --> <tx:annotation-driven transaction-manager="transactionManager"/>
2、Spring事务配置规则
spring事务中可配置的规则有:
传播行为,隔离级别,只读属性,超时属性,不影响提交的异常,导致回滚的异常
传播行为可配置的属性:
PROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
PROPAGATION_SUPPORTS--支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY--支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER--以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED--如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。
使用spring xml配置的写法为:<tx:method name="*" propagation="REQUIRED"/>
隔离级别可配置的属性有:
ISOLATION_DEFAULT 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别
ISOLATION_READ_UNCOMMITTED 这是事务最低的隔离级别,它充许别外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读。
ISOLATION_READ_COMMITTED 保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。这种事务隔离级别可以避免脏读出现,但是可能会出现不可重复读和幻像读。
ISOLATION_REPEATABLE_READ 这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)。
ISOLATION_SERIALIZABLE 这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读外,还避免了幻像读。
使用 spring xml配置的写法为:<tx:method name="*" isolation="DEFAULT"/>
只读属性(read-only>
事务的只读属性是指,对事务性资源进行只读操作或者是读写操作。如果确定只对事务性资源进行只读操作,那么我们可以将事务标志为只读的,以提高事务处理的性能。
使用 spring xml配置的写法为:<tx:method name="*" read-only="true"/>
事务超时(timeout)
事务超时,就是指一个事务所允许执行的最长时间,如果超过该时间限制但事务还没有完成,则自动回滚事务。以 int 的值来表示超时时间,其单位是秒。
使用 spring xml配置的写法为:<tx:method name="*" timeout="-1"> ,timeout为-1,标识无事务超时设置
事务回滚(rollback-for || no-rollback-for):
通常情况下,如果在事务中抛出了未检查异常(继承自 RuntimeException 的异常),则默认将回滚事务。如果没有抛出任何异常,或者抛出了已检查异常,则仍然提交事务。
使用 spring xml配置的写法:<tx:method name="*"rollback-for="Throwable"/> Throwable为所有异常的超类,标识只要发生异常就回滚。
二、编程式spring事务的控制
编程方式的spring的事务控制有两种:基于TransactionManager的编程式事务管理和基于TransactionTemplate的编程方式
1)基于TransactionManager的编程式事务管理
使用接口PlatformTransactionManager、TransactionDefinition和 TransactionStatus
示例代码
public class CircleServiceImpl implementsCircleService{ private BaseDao baseDao; private TransactionDefinition definition; private PlatformTransactionManager manager; public boolean circleManage(.....){ TransactionStatus status = manager.getTransaction(definition); boolean result = false; try{ result = baseDao.execute(.....); manager.commit(status); }catch(Exception e){ result =fasle; manager.rollback(status); } return false; } }
相应的配置文件清单:
<bean id="circleService"class="footmark.spring.core.tx.programmatic.origin.BankServiceImpl"> <property name="baseDao"ref="baseDao"/> <property name="manager"ref="transactionManager"/> <propertyname="definition"> <beanclass="org.springframework.transaction.support.DefaultTransactionDefinition"> <propertyname="propagationBehaviorName"value="PROPAGATION_REQUIRED"/> </bean> </property> </bean>
public class CircleServiceImpl implementsCircleService{ privateCircleDao circleDao; privateTransactionTemplate transactionTemplate; ...... publicboolean transfer(.....){ return(Boolean)transactionTemplate.execute(newTransactionCallback(){ publicObject doInTransaction(TransactionStatus status){ Objectresult; try{ result=circleDao.transfer(.....); }catch(Exceptione){ status.setRollbackOnly(); result=false; } returnresult; } }); } }
相应的xml配置如下:
<bean id="circleService" class="footmark.spring.core.tx.programmatic.template.circleServiceImpl"> <propertyname="circleDao" ref="circleDao"/> <propertyname="transactionTemplate" ref="transactionTemplate"/> </bean>
参考资料:
http://www.ibm.com/developerworks/cn/education/opensource/os-cn-spring-trans/index.html