详解阿里P7架构师是怎么在Spring中实现事务暂停( 三 )


  1. 本地事务策略—支持单一资源的事务(通常是单个数据库),其包括org.springframework.jdbc.datasource.DataSourceTransactionManager和 org.springframework.orm.hibernate.HibernateTransactionManager 。
  2. 全局事务管理—支持可能跨越多个资源的全局事务 。其相应的类为org.springframework.transaction.jta.JtaTransactionManager,将事务委托给遵循JTA规范的事务协调器(通常为J2EE服务器,但不是强制的) 。
PlatformTransactionManager抽象的主要价值在于应用不再被绑定在特定的事务管理环境 。相反,事务策略可以很容易地切换—通过选择不同的PlatformTransactionManager实现类 。这就使得应用代码与声明事务分离保持一致,而不需要考虑应用组件所使用的环境了 。
例如,应用的初始版本可能布署在Tomcat上,与单个Oracle数据库交互 。这可以方便地利用Spring的事务分离特性,只要选择基于JDBC的DataSourceTransactionManager作为使用的事务策略 。Spring会分离事务,而JDBC驱动会执行相应的原始JDBC事务 。
相同应用的另一个版本可能会布署在WebLogic服务器上,使用两个Oracle数据库 。应用代码和事务分离不需要改变 。唯一不同的是选择作为JtaTransactionManager事务策略,让Spring来分离事务而WebLogic服务器的事务协调器来执行事务 。
JTA UserTransaction与JTA TransactionManager比较让我们来看一下Spring对JTA支持的细节 。虽然并非经常需要考虑这个细节但了解相关的细节还有必要的 。对简单的用例如前面章节的示例,标准的JtaTransactionManager定义已经足够了,缺省的Spring JtaTransactionManager设置会从标准JNDI位置(J2EE规范所定义的java:comp/UserTransaction)获取JTA的javax.transaction.UserTransaction对象 。这对大部分标准J2EE环境来说已经足够了 。
然而,缺省的JtaTransactionManager不能执行事务暂停(也就是说不支持PROPAGATION_REQUIRES_NEW和PROPAGATION_NOT_SUPPORTED) 。原因就在于标准的JTA UserTransaction接口不支持事务的暂停和恢复,而只支持开始和完成新的事务 。
为了实现事务的暂停,需要一个javax.transaction.TransactionManager实例,他提供了JTA定义的标准的暂停和恢复方法 。不幸的是,J2EE没有为JTA TransactionManager定义标准的JNDI位置!因此,我们需要使用厂商自己的定位机制 。
清单6:
<bean id="transactionManager"class="org.springframework.transaction.jta.JtaTransactionManager"> <property name="transactionManagerName"> <value>vendorSpecificJndiLocation</value> </property></bean>J2EE本质上没有考虑将JTA TransactionManager接口作为公共API的一部分 。JTA规范自身定义了将TransactionManager接口作为容器集成的想法 。虽然这是可以理解的,但是JTA TransactionManager的标准JNDI位置还是可以增加一定的价值,特别是对轻量级容器如Spring,这样任何J2EE服务器就可以用统一的方式来定位JTA TransactionManager了 。
不仅Spring的JtaTransactionManager可以从访问中获益,O/R映射工具如Hibernate, Apache OJB, and Kodo JDO也能得到好处,因为他们需要在JTA环境中执行缓存同步的能力(释放缓存意味着JTA事务的完成) 。这种注册事务同步的能力只有JTA TransactionManager接口才能提供,而UserTransaction是处理不了的 。因此,这些工具都需要实现自己的TransactionManager定位器 。
为JTA TransactionManager定义标准的JNDI位置是许多底层软件供应商最期望J2EE实现的功能 。如果J2EE5.0的规范制定团队能够认识到这个特性的重要性就太好了 。幸运地是,高级J2EE服务器如WebLogic Server已经考虑将JTA TransactionManager作为公共的API包含在扩展功能中 。
在WebLogic JTA中实现Spring的事务分离在WebLogic Server中,JTA TransactionManager官方的JNDI位置定义为javax.transaction.TransactionManager 。这个值可以在Spring的JtaTransactionManager中作为“transactionManagerName”使用 。原则上这样就可以在WebLogic's JTA系统中实现事务暂停了,也就是说支持PROPAGATION_REQUIRES_NEW和PROPAGATION_NOT_SUPPORTED行为 。
除了标准的JtaTransactionManager和其支持的通用配置选项外,Spring还提供了一个专用的WebLogicJtaTransactionManager适配器来直接利用WebLogic的JTA扩展 。
在享受自动探测WebLogic的JTA TransactionManager的便利之外,他提供超越标准JTA的三个重要特性:
  1. 事务命名—暴露出Spring的事务名给WebLogic Server,使得Spring事务在WebLogic的事务监听器可见 。缺省的,Spring会使用声明性事务的完整方法名 。
  2. 每事务隔离级别—将Spring事务属性中定义的隔离级别应用到WebLogic JTA事务中 。这使得每个事务都可以定义数据库的隔离级别,而这是标准JTA所不支持的 。


    推荐阅读