韩学敏 2012-12-05
要理解JTA的实现原理首先需要了解其架构:它包括事务管理器(TransactionManager)和一个或多个支持XA协议的资源管理器(ResourceManager)两部分,我们可以将资源管理器看做任意类型的持久化数据存储;事务管理器则承担着所有事务参与单元的协调与控制。根据所面向对象的不同,我们可以将JTA的事务管理器和资源管理器理解为两个方面:面向开发人员的使用接口(事务管理器)和面向服务提供商的实现接口(资源管理器)。其中开发接口的主要部分即为上述示例中引用的UserTransaction对象,开发人员通过此接口在信息系统中实现分布式事务;而实现接口则用来规范提供商(如数据库连接提供商)所提供的事务服务,它约定了事务的资源管理功能,使得JTA可以在异构事务资源之间执行协同沟通。以数据库为例,IBM公司提供了实现分布式事务的数据库驱动程序,Oracle也提供了实现分布式事务的数据库驱动程序,在同时使用DB2和Oracle两种数据库连接时,JTA即可以根据约定的接口协调者两种事务资源从而实现分布式事务。正是基于统一规范的不同实现使得JTA可以协调与控制不同数据库或者JMS厂商的事务资源,其架构如下图所示:
[img][/img]
开发人员使用开发人员接口,实现应用程序对全局事务的支持;各提供商(数据库,JMS等)依据提供商接口的规范提供事务资源管理功能;事务管理器(TransactionManager)将应用对分布式事务的使用映射到实际的事务资源并在事务资源间进行协调与控制。下面,本文将对包括UserTransaction、Transaction和TransactionManager在内的三个主要接口以及其定义的方法进行介绍。
面向开发人员的接口为UserTransaction(使用方法如上例所示),开发人员通常只使用此接口实现JTA事务管理,其定义了如下的方法:
begin()-开始一个分布式事务,(在后台TransactionManager会创建一个Transaction事务对象并把此对象通过ThreadLocale关联到当前线程上)
commit()-提交事务(在后台TransactionManager会从当前线程下取出事务对象并把此对象所代表的事务提交)
rollback()-回滚事务(在后台TransactionManager会从当前线程下取出事务对象并把此对象所代表的事务回滚)
getStatus()-返回关联到当前线程的分布式事务的状态(Status对象里边定义了所有的事务状态,感兴趣的读者可以参考API文档)
setRollbackOnly()-标识关联到当前线程的分布式事务将被回滚
面向提供商的实现接口主要涉及到TransactionManager和Transaction两个对象
Transaction代表了一个物理意义上的事务,在开发人员调用UserTransaction.begin()方法时TransactionManager会创建一个Transaction事务对象(标志着事务的开始)并把此对象通过ThreadLocale关联到当前线程。UserTransaction接口中的commit()、rollback(),getStatus()等方法都将最终委托给Transaction类的对应方法执行。Transaction接口定义了如下的方法:
commit()-协调不同的事务资源共同完成事务的提交
rollback()-协调不同的事务资源共同完成事务的回滚
setRollbackOnly()-标识关联到当前线程的分布式事务将被回滚
getStatus()-返回关联到当前线程的分布式事务的状态
enListResource(XAResourcexaRes,intflag)-将事务资源加入到当前的事务中(在上述示例中,在对数据库A操作时其所代表的事务资源将被关联到当前事务中,同样,在对数据库B操作时其所代表的事务资源也将被关联到当前事务中)
delistResourc(XAResourcexaRes,intflag)-将事务资源从当前事务中删除
registerSynchronization(Synchronizationsync)-回调接口,Hibernate等ORM工具都有自己的事务控制机制来保证事务,但同时它们还需要一种回调机制以便在事务完成时得到通知从而触发一些处理工作,如清除缓存等。这就涉及到了Transaction的回调接口registerSynchronization。工具可以通过此接口将回调程序注入到事务中,当事务成功提交后,回调程序将被激活。
TransactionManager本身并不承担实际的事务处理功能,它更多的是充当用户接口和实现接口之间的桥梁。下面列出了TransactionManager中定义的方法,可以看到此接口中的大部分事务方法与UserTransaction和Transaction相同。在开发人员调用UserTransaction.begin()方法时TransactionManager会创建一个Transaction事务对象(标志着事务的开始)并把此对象通过ThreadLocale关联到当前线程上;同样UserTransaction.commit()会调用TransactionManager.commit(),方法将从当前线程下取出事务对象Transaction并把此对象所代表的事务提交,即调用Transaction.commit()
begin()-开始事务
commit()-提交事务
rollback()-回滚事务
getStatus()-返回当前事务状态
setRollbackOnly()
getTransaction()-返回关联到当前线程的事务
setTransactionTimeout(intseconds)-设置事务超时时间
resume(Transactiontobj)-继续当前线程关联的事务
suspend()-挂起当前线程关联的事务
在系统开发过程中会遇到需要将事务资源暂时排除的操作,此时就需要调用suspend()方法将当前的事务挂起:在此方法后面所做的任何操作将不会被包括在事务中,在非事务性操作完成后调用resume()以继续事务(注:要进行此操作需要获得TransactionManager对象,其获得方式在不同的J2EE应用服务器上是不一样的)
下面将通过具体的代码向读者介绍JTA实现原理。下图列出了示例实现中涉及到的Java类,其中UserTransactionImpl实现了UserTransaction接口,TransactionManagerImpl实现了TransactionManager接口,TransactionImpl实现了Transaction接口