JTA是开发人员进行事务管理的接口,JTS是应用服务器使用的,实现了JTA的底层事务服务。
JTA进行分布式事务管理有两种方式:编程事务管理、声明性事务管理。
l 编程事务管理
使用编程事务管理,首先得获取Usertransaction,各应用服务器提供了JNDI查找服务。
InitialContext ctx = new InitialContext();
UserTransaction transaction =ctx.lookup("UserTransaction");
...
transaction.commit() 或 transaction.rollback();
其中不同的应用服务器给定的查找名称不同,如Jboss 查找名为“UserTransaction”,而Weblogic,查找名为"javax.transaction.UserTransaction"。
在EJB中时,编程事务管理又称之为BMT,Bean ManageTransaction。在EJB中需要使用配置文件或注解配置为BMT,Usertransaction可以直接从EJBContext中获取。
l 声明性事务管理
编程事务管理中,必须手动开启与结束事务,声明性事务管理,容器管理事务,开发人员不用编写任务代码,可以通过配置文件或注解,告诉容器如何管理事务。EJB声明性事务也称为容器管理事务,CMT,Container Manage Transaction。使用CMT,必须有EJB容器提供支持。
使用CMT仅要做的工作是配置事务属性,需要回滚时调用EJBContex方法setRollbackOnly()。
容器不会在应用发生异常时自行将事务标记为回滚,所有我们要在应用发生异常时告知容器回滚事务:setRollbackOnly()。
在CMT事务管理中,一个必然的决定,什么地方抛异常,什么地方和什么时机调用setRollbackOnly。一般的决策,开启事务的方法,具有事务管理的责任。
EJB中包含一个@ApplicationException注解,该注解告知应用服务器,当用异常抛出时是否自动将事务标记为回滚。带来的好处是不用写setRollbackOnly方法。缺点是注解针对异常类,只要抛出该异常,无论对象本身有没有开启事务,都会导致整体事务回滚,负责处理事务的方法无任何对回滚事务的补救。另一缺点是,将事务处理与异常处理混在一起,导致异常粒度过大。
三、 问题
JAVA平台提供的事务管理API多种多样,可以根据不的场景选择不同的事务管理API。但过多的选择,也带来一些问题。
1. 局部事务管理依赖于具体数据访问技术。事务管理代码与数据访问代码、业务代码混杂,将导致数据访问代码、业务代码不可重用;事务代码分散,降低了可重用性。
2. 无统一事务相关异常体系,需要事务管理代码处理checked exception.
3. 选择太多,缺少统一的事务抽象。
4. CMT必须借助于EJB容器。CMT代码清晰,事务管理与业务代码分离,但受限于容器。
有需求就有解决方案,Spring事务框架,对事务管理与数据访问关注点进行了分离与抽象,使开发人员仅关心事务界定。