乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      TransactionManager

       旭龍 2013-08-07
      您有沒有想過,為什么會有六種事務(wù)劃分屬性(NotSupported、Required、Supports、RequiresNew、Mandatory和Never)?這六種都是由容器托管事務(wù) (CMT)的bean來支持的,但如果使用的是bean托管事務(wù)(BMT),EJB規(guī)范所能提供的功能難道就只有通過UserTransaction接口啟動和提交/回滾事務(wù)嗎?顯然,CMT模型好像更強大,比如,BMT不能使當前事務(wù)掛起然后恢復,這就意味著在BMT bean中無法仿真RequiresNew和NotSupported劃分,至少是在使用UserTransaction接口時。

        雖然EJB規(guī)范并沒有解釋為什么會存在以上所提到的不對稱情況,但是在BMT模型中依然有一種用來使事務(wù)掛起然后恢復的合法方式。如果曾經(jīng)研究過javax.transaction包的內(nèi)容,您可能會注意到,與UserTransaction接口一起的還有一個TransactionManager接口,它看起來就像一個擴展的UserTransaction:同樣的方法——begin()、commit()和rollback(),再加上suspend()和resume()。

        如果能從EJB中得到一個TransactionManager實現(xiàn),我們就可以實現(xiàn)編程式地使事務(wù)掛起然后恢復的目標。雖然J2EE 1.3和EJB 2.0規(guī)范都未提到TransactionManager的可用性,但它們也都沒有明確表示禁止使用它。此外,對于CMT事務(wù)劃分,容器是從內(nèi)部使用Java Transaction API (JTA),因此,我們幾乎可以100%地肯定:TransactionManager是存在的,惟一的問題只是在代碼中獲得對它的引用。

        在這篇文章中,我們將了解如何利用幾個流行的容器來獲得一個TransactionManager,以及如何用它來擴展bean托管事務(wù)的功能,使它們和容器托管事務(wù)一樣強大。我們也將簡述一些涉及使用這些高級功能的風險,在文章的結(jié)尾,我們還將探討如何在流行的Spring框架中使用TransactionManager。
      在各種J2EE服務(wù)器中獲得TransactionManager的引用

        J2EE和EJB規(guī)范沒有描述任何獲得TransactionManager引用的標準方法,每個J2EE容器供應商可以隨意將其放置在任何地方,甚至不需提供任何機制,就可以從應用程序代碼中對它進行訪問。但在實踐中,如今所有的容器都有獲取它的機制。以下是一些如何從最流行的J2EE容器獲得TransactionManager引用的例子。
      拋出一個UserTransaction (WebLogic、Orion、OC4J)

        任何一個兼容J2EE的容器都必須使UserTransaction對象在JNDI中的java:comp/UserTransaction下可用。因為UserTransaction接口是TransactionManager的子集,所以一些J2EE容器供應商選擇為它們提供一種通用的實現(xiàn)。WebLogic 8、Orion 2和Oracle的OC4J EJB3預覽版都是這種方法的例子。在這些容器中,只要從JNDI中獲得一個UserTransaction對象,再把它轉(zhuǎn)到TransactionManager,就可以獲得對TransactionManager的引用。這可能是最簡單的一種情況。

      Java代碼  收藏代碼
      1. private TransactionManager getFromUserTransaction()   
      2.         throws Exception {  
      3.     InitialContext ctx = new InitialContext();  
      4.     UserTransaction ut = (UserTransaction)  
      5.         ctx.lookup("java:comp/UserTransaction");  
      6.     if (ut instanceof TransactionManager) {  
      7.         log("UserTransaction also TransactionManager");  
      8.         return (TransactionManager)ut;  
      9.     }  
      10.     return null;  
      11. }  


      直接從JNDI中獲取TransactionManager (JBoss、WebLogic)

        在JBoss 3和WebLogic 8中,可從JNDI獲取TransactionManager(雖然名稱不一樣),因此可以通過簡單的查找而獲得:

      Java代碼  收藏代碼
      1. private TransactionManager getFromJNDI()   
      2.         throws Exception {  
      3.     InitialContext ctx = new InitialContext();  
      4.     try {  
      5.         // WebLogic  
      6.         return (TransactionManager)  
      7.             ctx.lookup("javax.transaction.TransactionManager");  
      8.      }  
      9.      catch (Exception e) {  }  
      10.   
      11.     try {  
      12.         // JBoss  
      13.         return (TransactionManager)  
      14.             ctx.lookup("java:/TransactionManager");  
      15.     }  
      16.     catch (Exception e) { }  
      17.     return null;  
      18. }  


      從一個定制的工廠獲取TransactionManager (Websphere)

        在WebSphere 4/5/6中,TransactionManager的引用要從工廠類中獲取。但是,麻煩的是,工廠類的名稱隨WebSphere版本的不同而有所改變。

      Java代碼  收藏代碼
      1. public TransactionManager getFromWebsphereFactory()   
      2.         throws Exception {  
      3.      try {  
      4.         // WebSphere 5.1 or 6.0  
      5.         return   
      6.             com.ibm.ws.Transaction.TransactionManagerFactory  
      7.                 .getTransactionManager();  
      8.     }  
      9.     catch (ClassNotFoundException ex) {}  
      10.           
      11.     try {  
      12.         // WebSphere 5.0  
      13.         return   
      14.             com.ibm.ejs.jts.jta.TransactionManagerFactory  
      15.                 .getTransactionManager();  
      16.     }  
      17.     catch (ClassNotFoundException ex) {}  
      18.           
      19.     try {  
      20.         // WebSphere 4.0  
      21.         com.ibm.ejs.jts.jta.JTSXA..getTransactionManager();  
      22.     }  
      23.     catch (ClassNotFoundException ex) { }  
      24.   
      25.     return null;  
      26. }  


        在WebLogic 7/8/9中,對TransactionManager的引用可以通過在Weblogic 7的TxHelper中定義的靜態(tài)方法getTransactionManager()而獲得。該類在WebLogic 8中被否決了,而用TransactionHelper取而代之。

      Java代碼  收藏代碼
      1. public TransactionManager getFromWebLogicFactory()   
      2.     throws Exception {  
      3.      try {  
      4.         // WebLogic 8/9  
      5.         return   
      6.             weblogic.transaction.TransactionHelper  
      7.                 .getTransactionManager();  
      8.     }  
      9.     catch (ClassNotFoundException ex) {}  
      10.           
      11.     try {  
      12.         // WebLogic 7  
      13.         return   
      14.             weblogic.transaction.TxHelper  
      15.                 .getTransactionManager();  
      16.     }  
      17.     catch (ClassNotFoundException ex) {}  
      18.           
      19.     return null;  
      20. }  


      使用TransactionManager

        一旦成功地獲得TransactionManager引用,就可以用它來掛起和恢復事務(wù),正如以下的示例代碼所示。

      ...
      Java代碼  收藏代碼
      1. // obtain UserTransaction object and start transaction  
      2. InitialContext ctx = new InitialContext();  
      3. UserTransaction userTransaction = (UserTransaction)  
      4.     ctx.lookup("java:comp/UserTransaction");  
      5.   
      6. // start first transaction  
      7. userTransaction.begin();  
      8.               
      9. // obtain TransactionManager   
      10. // using one of the methods described above  
      11. TransactionManager tm = getTransactionManager();  
      12.   
      13. // suspend transaction  
      14. // suspend() returns reference to suspended  
      15. // Transaction object which later should be passed  
      16. // to resume()  
      17. Transaction transaction = tm.suspend();  
      18.                   
      19. // here you can do something outside of transaction  
      20. // or start new transaction,   
      21. // do something and then commit or rollback  
      22. userTransaction.begin();  
      23.       
      24. // commit subtransaction  
      25. userTransaction.commit();  
      26.   
      27. // resume suspended transaction  
      28. tm.resume(transaction);  
      29.   
      30. // commit first transaction  
      31. userTransaction.commit();  
      32. ...  


      正如您所看到的,在TransactionManager接口的幫助下,可以對UserTransaction所提供的標準功能進行擴展,在BMT代碼中實現(xiàn)與CMT bean相同的靈活性水平。

        需要知道的是,當事務(wù)被掛起時,并不意味著事務(wù)的計時器停止了。換言之,如果把事務(wù)的超時設(shè)定為30秒,而事務(wù)已掛起了20秒并恢復了,那么該事務(wù)只剩10秒就要到達超時了。事務(wù)的掛起會解除事務(wù)與正在運行的線程之間的關(guān)聯(lián),然后resume()調(diào)用會再次將其關(guān)連,而不影響事務(wù)超時計時器。
      已知問題

        因為J2EE規(guī)范并不要求TransactionManager在J2EE容器中的可用性以及功能(雖然從底層的JTA基礎(chǔ)架構(gòu)中我們知道它應該是存在的),所以有些應用服務(wù)器中存在一些問題。例如,在WebLogic 7、8以及9(beta版)中有種特別奇怪的現(xiàn)象:假如一個事務(wù)被標記為回滾(通過調(diào)用UserTransaction.setRollbackOnly ()),然后被掛起,當被掛起的事務(wù)嘗試恢復時,它將會出現(xiàn)如下的提示:

        javax.transaction.InvalidTransactionException: Attempt to resume an inactive transaction

        以下代碼說明了該行為:

      Java代碼  收藏代碼
      1. ...  
      2. // obtain UserTransaction object and start transaction  
      3. InitialContext ctx = new InitialContext();  
      4. UserTransaction userTransaction = (UserTransaction)  
      5.     ctx.lookup("java:comp/UserTransaction");  
      6. userTransaction.begin();  
      7.   
      8. // mark for rollback  
      9. userTransaction.setRollbackOnly();  
      10.               
      11. TransactionManager tm = getTransactionManager();  
      12.   
      13. // suspend transaction  
      14. Transaction transaction = tm.suspend();  
      15.                   
      16. // resume suspended transaction  
      17. // this call will fail with InvalidTransactionException  
      18. //  in WebLogic  
      19. tm.resume(transaction);  

      ...

        幸運的是,對于該問題,有一個應急方案。WebLogic的TransactionManager實現(xiàn)連同標準的resume (Transaction transaction)方法,有一個可用于替代的forceResume方法。以下的代碼展示了一種在WebLogic中運行代碼時需要用到的模式。注意,在這種情況下,應該把對TransactionManager的引用轉(zhuǎn)換到WebLogic的定制實現(xiàn)接口(WebLogic 7中的weblogic.transaction.TransactionManager或WebLogic 8以及更高版本中的weblogic.transaction.ClientTransactionManager)。

      ...
      // obtain UserTransaction object and start transaction
      Java代碼  收藏代碼
      1. InitialContext ctx = new InitialContext();  
      2. UserTransaction userTransaction = (UserTransaction)  
      3.     ctx.lookup("java:comp/UserTransaction");  
      4. userTransaction.begin();  
      5.   
      6. // mark for rollback  
      7. userTransaction.setRollbackOnly();  
      8.               
      9. TransactionManager tm = getTransactionManager();  
      10.   
      11. // suspend transaction  
      12. Transaction transaction = tm.suspend();  
      13.                   
      14. // resume suspended transaction  
      15. try {  
      16.     // first try standard JTA call  
      17.     tm.resume(transaction);  
      18. }  
      19. catch (InvalidTransactionException e) {  
      20.     // standard method failed, try forceResume()  
      21.     if (tm instanceof   
      22.         weblogic.transaction.ClientTransactionManager) {  
      23.         // WebLogic 8 and above  
      24.         ((weblogic.transaction.ClientTransactionManager)tm)  
      25.             .forceResume(transaction);  
      26.     }      
      27.     else if (tm instanceof   
      28.         weblogic.transaction.TransactionManager) {  
      29.         // WebLogic 7  
      30.         ((weblogic.transaction.TransactionManager)tm)  
      31.             .forceResume(transaction)  
      32.     }  
      33.     else {  
      34.         // cannot resume  
      35.         throw e;  
      36.     }  
      37. }  

      ...

      TransactionManager在Spring Framework中的用法

        在流行的Spring framework中,以上所描述的技術(shù)都被廣泛地用于事務(wù)代理。應該注意的是,每次使用PROPAGATION_REQUIRES_NEW或PROPAGATION_NOT_SUPPORTED、事務(wù)屬性以及JtaTransactionManager來配置Spring的TransactionProxyFactoryBean時, Spring就會用JTA的TransactionManager來掛起和恢復事務(wù)。Spring太智能了,但有時太智能了反而使我無法接受——甚至沒有指定,它就會發(fā)現(xiàn)容器中的TransactionManager。例如,當在一個Spring應用程序上下文中定義 JtaTransactionManager時,就可以為UserTransaction提供一個JNDI名,而如果UserTransaction也實現(xiàn)了它,它就將“自動檢測”TransactionManager。如上所示,這對WebLogic、Orion和Oracle OC4J都適用。

        有時,這可能并不是我們所想要的,尤其是當您想要嚴格遵循J2EE/EJB規(guī)范,并確保跨所有J2EE容器的完全可移植性的時候。正如我們所看到的,有時候編程式的事務(wù)掛起和恢復可能存在一些問題。雖然Spring知道如何繞過這些問題,至少是對于上面所描述的問題,即,在Welogic中,在掛起之前將事務(wù)標記為回滾。在這種情況下,可以在配置JtaTransactionManager時把 autodetectTransactionManager屬性設(shè)定為false。如果這么做了,那么任何使用 PROPAGATION_REQUIRES_NEW或PROPAGATION_NOT_SUPPORTED事務(wù)屬性的嘗試都會拋出 TransactionSuspensionNotSupportedException而失敗。但PROPAGATIO-REQUIRED、 PROPAGATION-SUPPORTS、PROPAGATION-MANDATORY以及PROPAGATION-NEVER應該會正常運行。這對應于JTA Usertransaction所提供的功能,而且在任一個兼容J2EE的容器中都起作用。

        以下是Spring應用程序上下文中的事務(wù)管理器定義,其中禁用了TransactionManager自動檢測:
      Xml代碼  收藏代碼
      1. <bean id="transactionManager" class=  
      2. "org.springframework.transaction.jta.JtaTransactionManager">  
      3.   <property name="userTransactionName">  
      4.     <value>javax.transaction.UserTransaction</value>  
      5.   </property>  
      6.   <property name="autodetectTransactionManager">  
      7.     <value>false</value>  
      8.   </property>  
      9. </bean>  


      結(jié)束語

        J2EE規(guī)范不要求對JIA TransactionManager接口的支持。但由于J2EE使用JTA作為它的底層事務(wù)基礎(chǔ)架構(gòu),所以幾乎所有的J2EE服務(wù)器都把它公開為 J2EE的擴展。存在一些已知的兼容性問題,而在某些情況下,可以用特定于容器的代碼來繞過這些問題。但是,如果需要實現(xiàn)編程式事務(wù)掛起,則J2EE中的 TransactionManager是一個強大的特性。只需首先在所選擇的J2EE服務(wù)器中檢測一下它是否可用就可以了。

        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多