EJB 3 事務管理探討

EJB事務的特點:

  提供聲明式事務與編程式事務

  聲明式事務:應用程序只需要關心業務邏輯,由容器來負責事務的管理。這是實踐中常用的方法。

  編程時事務:應用程序編碼人員自己寫事務代碼。

  ② EJB事務編程的類型

  A、CMT    容器管理事務

  B、BMT    Bean管理事務

  C、Client-MT    Client-Controlled Transaction客戶端管理事務

  實體Bean只能用CMT。

  CMT:

  由容器實現的遠程對象/攔截器,負責調用中間件服務。

  優點:在應用程序代碼中,不用編寫事務服務代碼;

  缺點:粗粒度,只能在方法級別控制事務。

 

  EJB Bean類中編程方式來使用事務(BMT):

  優點:細粒度地控制事務

  缺點:事務代理與業務代碼糾纏

  Client-controlled Transaction:

  優點:客戶端可以精確控制事務

  缺點:可能會因爲網絡問題引起是事務的回滾。

3、EJB事務邊界的劃分

  事務邊界:事務邊界是指事務從哪裏開始。

  CMT的事務特性:

  Required:Bean類的方法必須要在事務環境下運行,這是容器默認的事務機制。

  事務特性只能使用在CMT。

  RequiredNew:Bean類中的方法必須在一個新的事務環境下運行。

  Supports:Bean類的方法不需要支持事務。如果客戶端有事務,則繼續沿用原事務環境。

  Mandatory:Bean類中方法必須要在事務環境下運行。客戶端不啓動事務則報錯。

  NoSupported:Bean類中方法不支持事務。如果客戶端啓動了事務,則掛起該事務。

  Never:Bean類中的方法不支持事務。如果客戶端啓動了事務,則報錯。

  如果沒有指定參數,@TransactionAttribute 註釋使用REQUIRED 作爲默認參數。

 三、EJB事務的編程

  1、CMT

    @TransationManagement  用在類前,標註該EJB事務管理方式爲Bean | Container(默認)

    @TrasactionAttribute    用在方法前,標註事務特性(事務的邊界)

    @SessionContext.setRollbackOnly()  回滾標識,setRollbackOnly()方法必須在事務環境下運行。

    EJB容器對於非受查異常(主要指RuntimeException)會回滾,事務對於受查異常則會提交事務。

  2、BMT

  UserTransaction:

  ① interface

  ② 提供控制事務的方法

  ③ 由容器實現,可以使用@Resource注入

    UserTransaction.begin()| commit()| .rollback()

  3、客戶端控制事務

  調用EJB的方法,要求EJB必須採用CMT形式。

  4、事務的隔離性

  事務的隔離級別:

  A、Read uncommitted:性能最高

  B、Read committed:解決髒讀問題

  C、Repeatable read:解決重複讀取問題

  D、Serializable:解決幻讀問題

  EJB本身不提供隔離級別的設置,可以通過直接設置數據庫(連接池)的隔離級別。

 

由於CMT依靠容器開始、提交和回滾事務,所以會限制事務的邊界位置。而BMT則允許通過編程的方式來指定事務的開始、提交和回滾的位置。主要使用的是javax.transaction.UserTransaction接口。
例如:

如果使用有狀態的Session Bean且需要跨越方法調用維護事務,那麼BMT是你唯一的選擇,當然BMT這種技術複雜,容易出錯,且不能連接已有的事務,當調用BMT方法時,總會暫停已有事務,極大的限制了組件的重用。故優先考慮CMT事務管理。

  1. @Stateless)    
  2. @TransactionManagement(TransactionManagementType.BEAN)                                     
  3. public class ManagerBean {    
  4.     @Resource                                                          
  5.     private UserTransaction userTransaction;                           
  6.     
  7.     public void placeSnagItOrder(Item item, Customer customer){    
  8.         try {    
  9.             userTransaction.begin();                                   
  10.    
  11.                 validateCredit(customer);    
  12.                 .... 
  13.    
  14.             userTransaction.commit();                                   
  15.         } catch (CreditValidationException cve) {                      
  16.             userTransaction.rollback();                                
  17.         } catch (CreditProcessingException cpe){                      
  18.             userTransaction.rollback();                               
  19.         } 
  20. ..... 
  21.     }    
  22. }   

 

 

@TransactionManagement(TransactionManagementType.BEAN) 指定了事務的類型爲BMT,上面沒有用到@TransactionAttribute,因爲它只適用於CMT,在上面代碼中,可以顯示的指定事務的開始與提交,因此更加的靈活。上面最關鍵的地方是注入了UserTransaction資源。其中獲得UserTransaction資源的方式有三種,除了用EJB資源的方式注入以外,還有以下兩種方式:
(1) JNDI查找

  1. Context context = new InitialContext();    
  2. UserTransaction userTransaction = (UserTransaction) context.lookup(“java:comp/UserTransaction”);    
  3. userTransaction.begin();    
  4. userTransaction.commit();   

如果在EJB之外,則可使用此方法,如在不支持依賴注入的JBoss4.2.2的Web工程或helper class即幫助器類中都可以。

(2)EJBContext

  1. @Resource     
  2. private SessionContext context;    
  3. ...    
  4. UserTransaction userTransaction = context.getUserTransaction(); userTransaction.begin();       
  5. userTransaction.commit();   

getUserTransaction方法只能在BMT中使用。如果在CMT中使用,則會拋出IllegalStateException異常。且在BMT中不能使用EJBContext的getRollbackOnly和setRollbackOnly方法,如果這樣使用,也會拋出IllegalStateException異常。

  @TransactionAttribute(TransactionAttributeType.REQUIRED)
  public void insertProduct(String name, Float price, boolean error) { 

  }

其中,@TransactionAttribute(TransactionAttributeType.REQUIRED)表示指定事務的類型。
如果省略,默認爲CMT方式。
@TransactionAttribute(TransactionAttributeType.REQUIRED)通知容器如何管理事務,
事務的屬性控制了事務的使用範圍,因爲事務之間的關係非常的複雜,這個屬性主要是用來處理事務與事務之間怎樣來處理的的問題。

  1. 如果產生一個系統異常,容器將自動回滾該事務。 EJBException是RuntimeException的子類,即也是一個系統運行時異常。
    如果Bean拋出一個普通的非繼承自RutimeException應用異常,事務將不會自動回滾,但可以
    通過調用EJBContext的SetRollbackOnly回滾。 EJB上下文還有一個getRollbackOnly方法,通過返回一個boolean值來確定CMT事務是否已被標記爲回滾。如果開始非常耗資源的操作前判斷此bean的事務已被標記爲回滾,則可以節約很多系統資源。
    對於上面的異常回滾操作,還有一更加優雅的方式:
    @ApplicationException(rollback=true)                                   
  2. public class CreditValidationException extends Exception {             

 

  1. @ApplicationException(rollback=true)                                   
  2. public class CreditProcessingException extends Exception {            

 

  1. //系統異常   
  2. @ApplicationException(rollback=false)                                   
  3. public class DatabaseException extends RuntimeException {   @ApplicationExcepti把JAVA覈對與不覈對的異常標識爲應用程序異常。其rollback默認爲false,表示程序不會導致CMT自動回滾。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章