Spring 与EJB 事务管理对比。
二者的相同点:
都提供了编程式和声明式事务支持。
二者的不同点:
spring 支持的是局部事务管理,也就是本地事务,不能用于多个事务性资源
EJB 支持全局事务管理,即可以管理多个事务性资源
尽管EJB 的事务管理似乎比spring 强大,我们在更多情况下用的也是spring 的事务管理,
除非有特殊的要求(例如:一个事务操作需要用到两个数据库),因为全局事务应该
由实现了JTA 的服务器管理(jboss, weblogic 等),因此也只能在服务器环境中才能使用。
一. spring 的声明式事务管理:
spring 的声明式事务管理是通过Spring AOP 实现的。
spring 提供了基于各种平台的事务管理器。首先需要在xml 文件中配置相应的事务管理器类。
如果直接使用JDBC 来完成应用程序的持久化,需要配置如下代码:
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
如果使用Hibernate3 来完成持久化,需要如下配置:
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
注:其中dataSource 是事先配置好的。
如果使用的是其他的持久化工具,也是添加与上面类似配置。
然后,将transactionManager- 注入给tx:advice ,再将tx:advice 注入给aop:config ,
这样事务切面就被添加到相应的业务方法上了。
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="get*" propagation="REQUIRED" />
<tx:method name="*" propagation="SUPPORTS" read-only="true" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:advisor pointcut="execute(*.*..XXX(..))" advice-ref="txAdvice" />
</aop:config>
说明:tx aop 两个命名空间都需要声明,完整的根节点声明为:
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
</beans>
Spring 中事务的5 个属性:
1. 传播性:
在org.springframework.transaction.TransactionDefinition 中定义了很多中传播属性,
最长用的有一下两种:
progaration="REQUIRED" ,这是默认值,表示的意思是如果当前不存在事务,
则会启动一个事务;如果当前存在事务,则会加入到当前事务。
progaration="SUPPORTS" 表示:如果没有事务,就不管事务;如果有事务,就
加入到当前事务中。一般用于查询语句。
2. 回滚条件:
缺省情况下,RuntimeException 及其子类被抛出时立即回滚;已检查异常被抛出时则会提交
如果要自己定义何时回滚,可以添加rollback-for 和no-rollback-for 属性。例如:
rollback-for="XxxException"
no-rollback-for="YyyException"
表示抛出 XxxException 异常时回滚,抛出YyyException 时不回滚,而不再考虑它们是
已检查还是未检查的异常。
3. 只读优化: read-only
暗示底层存储优化当前操作
4. 隔离级别: isolation
5. 超时: timeout="5"
二. EJB 的声明式事务管理:
分布式事务有两种情况:
1 多个资源
2 分布式组件
国际上提出了一种分布式事务解决方案的标准OTS (Object Transaction Service )
JavaEE 对OTS 做了实现,即JTS (Java Transaction Service )
对于开发者,不需要了解它们是怎么实现的,因为java 为我们提供了操作JTS 的上 层接口 JTA (Java Transaction API )
如何使用JTA :
1 编程方式:
核心接口是UserTransaction ,可以通过jndi 服务获得。
jndi 名: UserTransaction
用法:begin() commit() rollback();
2 声明方式:(缺省方式)
EJB 中的属性只有一个属性,即传播性。
每个方法缺省的事务传播属性是 REQUIRED
也就是说,在一般情况下不需要自己管理事务。
如果出于性能的考虑,确实需要更改事务的传播属性,则可以用标注声明:
@TransactionAttribte(TransactionAttributeType.NOT_SUPPORTED)