BlogJava 首頁 新隨筆 聯系 聚合 管理
            1 Posts :: 6 Stories :: 0 Comments :: 0 Trackbacks
           JTA概要介紹

            Java事務API(JTA;Java Transaction API)和它的同胞Java事務服務(JTS;Java Transaction Service),為J2EE平臺提供了分布式事務服務。一個分布式事務(distributed transaction)包括一個事務管理器(transaction manager)和一個或多個資源管理器(resource manager)。一個資源管理器(resource manager)是任意類型的持久化數據存儲。事務管理器(transaction manager)承擔著所有事務參與單元者的相互通訊的責任。下車站顯示了事務管理器和資源管理的間的關系。

            JTA事務比JDBC事務更強大。一個JTA事務可以有多個參與者,而一個JDBC事務則被限定在一個單一的數據庫連接。下列任一個Java平臺的組件都可以參與到一個JTA事務中:

            .JDBC連接

            .JDO PersistenceManager 對象

            .JMS 隊列

            .JMS 主題

            .企業JavaBeans(EJB)

            .一個用J2EE Connector Architecture 規范編譯的資源分配器。

            使用JTA的事務劃分

            要用JTA來劃分一個事務,應用程序調用javax.transaction.UserTransaction接口中的方法。示例4顯示了一個典型的JNDI搜索的UseTransaction對象。

          import javax.transaction.*;
          import javax.naming.*;
          // ...
          InitialContext ctx = new InitialContext();
          Object txObj = ctx.lookup(";java:comp/UserTransaction";);
          UserTransaction utx = (UserTransaction) txObj;

            應用程序有了UserTransaction對象的引用之后,就可以象示例5那樣來起動事務。

          utx.begin();
          // ...
          DataSource ds = obtainXADataSource();
          Connection conn = ds.getConnection();
          pstmt = conn.prepareStatement(";UPDATE MOVIES ...";);
          pstmt.setString(1, ";Spinal Tap";);
          pstmt.executeUpdate();
          // ...
          utx.commit();
          // ...

            當應用程序調用commit()時,事務管理器使用兩段提交協議來結束事務。JTA事務控制的方法:

            .javax.transaction.UserTransaction接口提供了下列事務控制方法:

          .public void begin()
          .public void commit()
          .public void rollback()
          .public void getStatus()
          .public void setRollbackOnly()
          .public void setTransactionTimeout(int)

            應用程序調用begin()來起動事務,即可調用commit()也可以調用rollback()來結束事務。

            使用JTA和JDBC

            開發人員經常使用JDBC來作為DAO類中的底層數據操作。如果計劃使用JTA來劃分事務,你將需要一個實現了javax.sql.XADataSource,javax.sql.XAConnection和javax.sql.XAResource接口JDBC的驅動。實現了這些接口的驅動將有能力參與到JTA事務中。一個XADataSource對象是一個XAConnection對象的工廠。XAConnections是參與到JTA事務中的連接。

            你需要使用應用程序服務器管理工具來建立XADataSource對象。對于特殊的指令請參考應用程序服務器文檔和JDBC驅動文檔。

            J2EE應用程序使用JNDI來查找數據源。一旦應用程序有了一個數據源對象的引用,這會調用javax.sql.DataSource.getConnection()來獲得數據庫的連接。

            XA連接區別于非XA連接。要記住的是XA連接是一個JTA事務中的參與者。這就意味著XA連接不支持JDBC的自動提交特性。也就是說應用程序不必在XA連接上調用java.sql.Connection.commit()或java.sql.Connection.rollback()。相反,應用程序應該使用UserTransaction.begin()、UserTransaction.commit()和UserTransaction.rollback().

            選擇最好的方法

            我們已經討論了JDBC和JTA是怎樣劃分事務的。每一種方法都有它的優點,回此你需要決定為你的應用程序選擇一個最適應的方法。 在我們團隊許多最近的對于事務劃分的項目中使用JDBC API來創建DAO類。這DAO類總結如下:

            .事務劃分代碼被嵌入到DAO類內部

            .DAO類使用JDBC API來進行事務劃分

            .調用者沒有劃分事務的方法

            .事務范圍被限定在一個單一的JDBC連接

            JDBC事務對復雜的企業應用程序不總是有效的。如果你的事務將跨越多個DAO對象或多個數據庫,那么下面的實現策略可能會更恰當:

            .用JTA對事務進行劃分

            .事務劃分代碼被DAO分開

            .調用者承擔劃分事務的責任

            .DAO參與一個全局的事務中

            JDBC方法由于它的簡易性而具有吸引力,JTA方法提供了更多靈活性。你選擇什么樣的實現將依賴于你的應用程序的特定需求。

            日志記錄和DAO

            一個好的DAO實現類將使用日志記錄來捕獲有關它在運行時的行為細節。你可以選擇記錄異常、配置信息、連接狀態、JDBC驅動程序的元數據或查詢參數。日志對開發整個階段都是有益的。我經常檢查應用程序在開發期間、測試期間和產品中的日志記錄。

            在這段中,我們將展現一段如何把Jakarta Commaons Logging結合中一個DAO中的例子。在我們開始之前,讓我們先回顧一些基礎知識。

            選擇一個日志例庫

            許多開發人員使用的基本日志形式是:System.out.println和System.err.println.Println語句。這種形式快捷方便,但它們不能提供一個完整的日志系統的的能力。下表列出了Java平臺的日志類庫:

          日志類庫 開源嗎? URL
          Java.util.logging http://java.sun.com/j2ee
          Jakarta Log4j http://hajarta.apache.org/log4j/
          Jakarta Commons Logging http:/Jakarta.apache.org/commons/logging.html

            Java.util.logging是J2SE1.4平臺上的標準的API。但是,大多數開發人員都認為Jakarta Log4j提供了更大的功能性和靈活性。Log4j超越java.util.logging的優點之一就是它支持J2SE1.3和J2SE1.4平臺。

            Jakarta Commons Logging能夠被用于和java.util.loggin或Jakarta Log4j一起工作。Commons Logging是一個把你的應用程序獨立于日志實現的提取層。使用Commons Logging你能夠通過改變一個配置文件來與下面的日志實現來交換數據。Commons Logging被用于JAKARTA Struts1.1和Jakarta HttpClient2.0中。

            一個日志示例

            示例7顯示了在一個DOA類中怎樣使用Jakarta Commons Logging

          import org.apache.commons.logging.*;
          class DocumentDAOImpl implements DocumentDAO
          {
          static private final Log log = LogFactory.getLog(DocumentDAOImpl.class);
          public void deleteDocument(String id)
          {
          // ...
          log.debug(";deleting document: "; + id);
          // ...
          try
          {
          // ... data operations ...
          }
          catch (SomeException ex)
          {
          log.error(";Unable to delete document"; ex);
          // ... handle the exception ...
          }
          }
          }

            日志是評估應用程序的基本部分。如果你在一個DAO中遇到了失敗,日志經常會為理解發生的什么錯誤提供最好的信息。把日志結合到你的DAO中,確保得到調試和解決問題的有效手段。

            DAO中的異常處理

            我們已經看了事務劃分和日志記錄,并且現在對于它們是怎樣應用于數據訪問對象的有一個深入的理解。我們第三部分也是最后要討論的是異常處理。下面的一些簡單的異常處理方針使用你的DAO更容易使用,更加健壯和更具有可維護性。

            在實現DAO模式的時候,要考濾下面的問題:

            .在DAO的public接口中的方法將拋出被檢查的異常嗎?

            .如果是,將拋出什么樣的檢查性異常?

            .在DAO實現類中怎能樣處理異常。

            在用DAO模式工作的過程中,我們的團隊為異常處理開發了一組方針。下面的這些方針會很大程度的改善你的DAO:

            .DAO方法應該拋出有意義的異常。

            .DAO方法不應該拋出java.lang.Exception異常。因為java.lang.Exception太一般化,它不能包含有關潛在問題的所有信息。

            .DAO方法不應該拋出java.sql.SQLException異常。SQLException是一個底層的JDBC異常,DAO應用努力封裝JDBC異常而不應該把JDBC異常留給應用程序的其它部分。

            .在DAO接口中的方法應該只拋出調用者期望處理的檢查性異常。如果調用者不能用適當的方法來處理異常,考濾拋出不檢查性(運行時run-time)異常。

            .如果你的數據訪問代碼捕獲了一個異常,不可要忽略它。忽略捕獲異常的DAO是很處理的。

            .使用異常鏈把底層的異常傳遞給高層的某個處理器。

            .考濾定義一個標準的DAO異常類。Spring框架提供了一個優秀的預定義的DAO異常類的集合。

            看Resources,查看有異常和異常處理技術的更詳細信息。

            實現示例:MovieDAO

            MoveDAO是一個示范了在這篇文章中所討論的所有技術,包括事務劃分、日志記錄和異常處理。你會在Resources段找到MovieDAO的源代碼。它被分下面的三個包:

          .daoexamples.exception
          .daoexamples.move
          .daoexamples.moviedemo

            這個DAO模式的實現由下面的類和接口組成:

          .daoexamples.movie.MovieDAOFactory
          .daoexamples.movie.MovieDAO
          .daoexamples.movie.MovieDAOImpl
          .daoexamples.movie.MovieDAOImplJTA
          .daoexamples.movie.Movie
          .daoexamples.movie.MovieImple
          .daoexamples.movie.MovieNotFoundException
          .daoexamples.movie.MovieUtil

            MovieDAO接口定義了DAO的數據操作。這個接口有如下五個方法:

          .public Movie findMovieById(String id)
          .public java.util.Collection findMoviesByYear(String year)
          .public void deleteMovie(String id)
          .public Movie createMovie(String rating,String year,String title)
          .public void updateMovie(String id,String rating,String year,String title)

            daoexamples.movie包包含了兩個MovieDAO接口的實現。每個實現使用了一個同的事務劃分方法,如下表所示:

            MovieDAOImpl MovieDAOImplJTA
          實現了MovieDAO接口嗎? Yes Yes
          通過JNDI獲得DataSource嗎? Yes Yes
          從一個DataSource獲得java.sql.Connection對象嗎? Yes Yes
          DAO界定內部的事務嗎? Yes No
          使用JDBC事務嗎? Yes No
          使用一個XA DataSource嗎? No Yes
          分擔JTA事務嗎? No Yes

            MovieDAO 示范應用程序

            這個示范應用程序是一個叫做daoexamples.moviedemo.DemoServlet.DemoServlet的servlet類,它使用Movie DAO來查詢和更新一個表中的movie數據。

            這個servlet示范了把JTA感知的MovieDAO和Java消息服務組合到一個單一的事務中,如示例8所示:

          UserTransaction utx = MovieUtil.getUserTransaction();
          utx.begin();
          batman = dao.createMovie(";R";
          ";2008";
          ";Batman Reloaded";);
          publisher = new MessagePublisher();
          publisher.publishTextMessage(";I’ll be back";);
          dao.updateMovie(topgun.getId(),
          ";PG-13";
          topgun.getReleaseYear(),
          topgun.getTitle());
          dao.deleteMovie(legallyblonde.getId());
          utx.commit();

            要運行這個范例應用程序,在你的應用程序服務器中配置一個XA 數據源和一個非XA數據源。然后布署daoexamples.ear文件。這個應用程序將運行在任何與J2EE兼容的應用程序服務器。
          posted on 2006-01-12 20:24 阿獸學習 閱讀(548) 評論(0)  編輯  收藏

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 阿拉善左旗| 北票市| 盐池县| 三明市| 杭锦后旗| 武山县| 加查县| 五原县| 竹溪县| 曲阳县| 樟树市| 梅州市| 化州市| 徐水县| 新泰市| 自贡市| 蒲江县| 泌阳县| 三亚市| 永修县| 新巴尔虎左旗| 资溪县| 樟树市| 大洼县| 黄大仙区| 勐海县| 白城市| 华池县| 仙游县| 泰州市| 区。| 方山县| 永善县| 晋城| 江华| 琼中| 大洼县| 宿州市| 垦利县| 海阳市| 南昌县|