手工调用jdbc的connection事务方法和使用JTA接口都属于编程式开发,在EJB中叫BMT(Bean管理事务)。
JTA最重要的接口就是UserTransaction和它的六个方法-begin,commit,rollback,getStatus,setRollbackonly,setTransactionTimeout。
程序需要UserTransaction时可以从JNDI领取,不过JNDI名随应用服务器不同而不同。EJB3里可以直接用个@Resource注入。
前面都是铺垫,这个才是主打的事务模型,如EJB的CMT(容器管理事务)和Sprin。
其中EJB2.0,Spring1.0在部署描述符和applicationContext.xml中定义,而EJB3.0和Spring2.0则采用annotation。
这里JavaEE与Spring的定义基本相同:
可见,Required是默认的设置,Supports是只读方法的最佳选择。
级别越低越安全效率也越低。隔离级别需要相关资源支持,如重复读在Oracle里会降级为ReadCommited。Spring里默认的Default级别完全看数据源的脸色行事。
EJB里,想rollback只能sessionContext.setRollbackOnly(),或者抛出EJBException。(EJB3还可以annotation设置某些自定义Exception可以触发rollback)
在Spring里,同样只会rollback unchecked exception(RuntimeExcption及子类),而checked exception(Exception及子类)是不会rollback的,除非你特别声明。
@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW,rollbackFor = {MyException1.class,MyException2.class})
因此所有在service层方法中用throws定义的Exception,都必须在事务定义中进行rollback设定。(请勿善忘)
所有在service层方法中c被atch处理了的异常,又希望容器辅助rollback的话,必须重抛一个预定义的RuntimeException的子类。(请勿回望)
Spring不希望编程式事务管理。
Spring也不希望使用EJB CMT--CMT依赖于EJB而无法用于POJO,依赖于JTA全局事务对单数据源场景造成了浪费,而且rollback机制比较麻烦(必须为EJBException或手工setRollbackOnly())。
因此Spring通过AOP实现了对POJO的整套宣告式事务体系;对jdbc,hibernate,jpa,jms等local数据源和JTA实现了统一的事务管理机制,而且支持本地资源与JTA在配置文件级的切换,而且改进了rollback机制。
1)一个本地事务管理器:
"transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> "entityManagerFactory" ref="entityManagerFactory" />
2)Spring就会把请求都转发到应用服务器的JTA对象上(注意此时数据源也需要改为用JNDI从应用服务器获取)。
"myTxManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>
3)应用服务器专有的类型的JTA事务管理器:
"myTxManager" class="org.springframework.transaction.jta.WebLogicJtaTransactionManager"/>
在事务管理程序周围的数字框框相应于JTA的三个接口部分: 1.UserTransaction?javax.transaction.UserTransaction 接口提供能够编程地控制事务处理范围的应用程序。 javax.transaction.UserTransaction方法开启一个全局事务并且使用调用线程与事务处理关联。 2.Transaction Manager?javax.transaction.TransactionManager接口允许应用程序服务器来控制代表正在管理的应用程序的事务范围。 3.XAResource?javax.transaction.xa.XAResource接口是一个基于X/Open CAE Specification的行业标准XA接口的Java映射。