【转】应用EJB3的事务管理功能

【转】使用EJB3的事务管理功能

我们一般编程都会使用到两种模型实现事务管理:
1.         编程式事务
手工调用jdbc的connection事务方法和使用JTA接口都属于编程式开发,在EJB中叫BMT(Bean管理事务)。
    JTA最重要的接口就是UserTransaction和它的六个方法-begin,commit,rollback,getStatus,setRollbackonly,setTransactionTimeout。
       关于JTA事务和JDBC事务的使用参考:
http://hi.baidu.com/coolcat%5Fpolice/blog/item/57af71123e01c6cbc2fd78a6.html
2.         宣告式事务
EJB的CMT(容器管理事务)就是一个宣告式事务。利用容器,当应用出现失败或异常时,它保证了数据库的完整性。最常见的事务是定义在session bean 的方法上,方法中所有的数据库操作只有在方法正常退出时才会提交,如果方法抛出未捕获的异常,事务管理将回滚所有变更。
@TransactionAttribute 注释一个方法用作定义一个需要事务的方法。它可以有以下参数(TransactionAttributeType.参数名):
Required:如果Context中有事务就加入,没有就自己创建一个。(最常用设置)
Mandatory:永远加入一个事务。如果当前Context没有事务,抛出异常。(那些不打算自己负责rollback事务的方法,必须加入到别人的事务,由别人来控制rollback)
RequiresNew:永远新建一个事务。(那些不管别人如何,自己必须提交事务的方法,比如审计信息是一定要写的)
Supports:如果有事务就加入,如果没有就算了。永远不会创建新事务。(一般用于只读方法,不会主动创建事务,但如果当前有事务就加入,以读到事务中未提交的数据)
NotSupported:永远不使用事务,如果当前有事务,挂起事务。(那些有可能抛异常但异常并不影响全局的方法)
Never:不能在有当前事务的情况下调用本方法。
可见,Required是默认的设置,Supports是只读方法的最佳选择。
注意,EJB里,想rollback只能sessionContext.setRollbackOnly(),或者抛出EJBException。(EJB3还可以annotation设置某些自定义Exception可以触发rollback)。另外,不需要远程调用的接口就不需配置EJB注释,但最好都显式标出。
在Spring里,同样只会回滚 unchecked exception(RuntimeExcption及子类),而checked exception(Exception及子类)是不会rollback的,除非你特别声明。
简单使用的话,直接在service层里面需要rollback的地方throw new RuntimeException("异常信息");
事务隔离级别
ReadUncommited:本事务可以看到另一事务未提交的数据。脏读。
ReadCommited:本事务只可以看到另一事务已提交的数据。不可重复读。
RepeatableRead:可重复读。在一个事务内,第一次读到的数据,在本事务没有提交前,无论另一个事务如何提交数据,本事务读到的数据都是不变的。
Serializable:串行化,同时只有一个事务能读相同的数据。
    级别越低越安全效率也越低。隔离级别需要相关资源支持,如重复读在Oracle里会降级为ReadCommited。