拾貝殼

          走過(guò)的路
          隨筆 - 39, 文章 - 1, 評(píng)論 - 14, 引用 - 0
          數(shù)據(jù)加載中……

          JTA和JDBC事務(wù)

           一般情況下,J2EE應(yīng)用服務(wù)器支持JDBC事務(wù)、JTA事務(wù)、容器管理事務(wù)。這里討論JTA和JDBC事務(wù)的區(qū)別。這2個(gè)是常用的DAO模式事務(wù)界定方式。
          JDBC 事務(wù)
           JDBC 事務(wù)是用 Connection 對(duì)象控制的。JDBC Connection 接口( java.sql.Connection )提供了兩種事務(wù)模式:自動(dòng)提交和手工提交。
          ★ 在jdbc中,事務(wù)操作缺省是自動(dòng)提交。也就是說(shuō),一條對(duì)數(shù)據(jù)庫(kù)的更新表達(dá)式代表一項(xiàng)事務(wù)操作,操作成功后,系統(tǒng)將自動(dòng)調(diào)用commit()來(lái)提交,否則將調(diào)用rollback()來(lái)回滾。
          ★ 在jdbc中,可以通過(guò)調(diào)用setAutoCommit(false)來(lái)禁止自動(dòng)提交。之后就可以把多個(gè)數(shù)據(jù)庫(kù)操作的表達(dá)式作為一個(gè)事務(wù),在操作完成后調(diào)用commit()來(lái)進(jìn)行整體提交,倘若其中一個(gè)表達(dá)式操作失敗,都不會(huì)執(zhí)行到commit(),并且將產(chǎn)生響應(yīng)的異常;此時(shí)就可以在異常捕獲時(shí)調(diào)用rollback()進(jìn)行回滾。這樣做可以保持多次更新操作后,相關(guān)數(shù)據(jù)的一致性,示例如下:

              try {

          conn = 

          DriverManager.getConnection    

          ("jdbc:oracle:thin:@host:1521:SID","username","userpwd";

                 conn.setAutoCommit(false);//禁止自動(dòng)提交,設(shè)置回滾點(diǎn)

                 stmt = conn.createStatement();

          stmt.executeUpdate(“alter table …”); //數(shù)據(jù)庫(kù)更新操作1

          stmt.executeUpdate(“insert into table …”); //數(shù)據(jù)庫(kù)更新操作2

                 conn.commit(); //事務(wù)提交

               }catch(Exception ex) {    

                   ex.printStackTrace();

                   try {

                    conn.rollback(); //操作不成功則回滾

                    }catch(Exception e) {

          e.printStackTrace();

                     }

          }

           JDBC 事務(wù)的一個(gè)缺點(diǎn)是事務(wù)的范圍局限于一個(gè)數(shù)據(jù)庫(kù)連接。一個(gè) JDBC 事務(wù)不能跨越多個(gè)數(shù)據(jù)庫(kù)。
          JTA事務(wù)
           JTA(Java Transaction API) 為 J2EE 平臺(tái)提供了分布式事務(wù)服務(wù)。
           要用 JTA 進(jìn)行事務(wù)界定,應(yīng)用程序要調(diào)用 javax.transaction.UserTransaction 接口中的方法。例如:
           utx.begin();
                // ...
                DataSource ds = obtainXADataSource();
                Connection conn = ds.getConnection();
                pstmt = conn.prepareStatement("UPDATE MOVIES ...");
                pstmt.setString(1, "Spinal Tap");
                pstmt.executeUpdate();
                // ...
                utx.commit();

           讓我們來(lái)關(guān)注下面的話:
           “用 JTA 界定事務(wù),那么就需要有一個(gè)實(shí)現(xiàn) javax.sql.XADataSource 、 javax.sql.XAConnection 和 javax.sql.XAResource 接口的 JDBC 驅(qū)動(dòng)程序。一個(gè)實(shí)現(xiàn)了這些接口的驅(qū)動(dòng)程序?qū)⒖梢詤⑴c JTA 事務(wù)。一個(gè) XADataSource 對(duì)象就是一個(gè) XAConnection 對(duì)象的工廠。 XAConnection s 是參與 JTA 事務(wù)的 JDBC 連接。”
           要使用JTA事務(wù),必須使用XADataSource來(lái)產(chǎn)生數(shù)據(jù)庫(kù)連接,產(chǎn)生的連接為一個(gè)XA連接。
           XA連接(javax.sql.XAConnection)和非XA(java.sql.Connection)連接的區(qū)別在于:XA可以參與JTA的事務(wù),而且不支持自動(dòng)提交。
               Note:
          Oracle, Sybase, DB2, SQL Server等大型數(shù)據(jù)庫(kù)才支持XA, 支持分布事務(wù)。
          My SQL 連本地都支持不好,更別說(shuō)分布事務(wù)了。
          JTA方式的實(shí)現(xiàn)過(guò)程
             用XADataSource產(chǎn)生的XAConnection它擴(kuò)展了一個(gè)getXAResource()方法,事務(wù)通過(guò)這個(gè)方法把它加入到事務(wù)容器中進(jìn)行管理.對(duì)于調(diào)用者來(lái)說(shuō),根本看不到事務(wù)是如果管理的,你只要聲明開始事務(wù),告訴容器我下面的操作要求事務(wù)參與了,最后告訴事務(wù)說(shuō)到這兒可以提交或回滾了,別的都是黑箱操作。
           在使用JTA之前,你必須首先實(shí)現(xiàn)一個(gè)Xid類用來(lái)標(biāo)識(shí)事務(wù)(在普通情況下這將由事務(wù)管理程序來(lái)處理)。Xid包含三個(gè)元素:formatID、gtrid(全局事務(wù)標(biāo)識(shí)符)和bqual(分支修飾詞標(biāo)識(shí)符)。
           下面的例子說(shuō)明Xid的實(shí)現(xiàn):

          import javax.transaction.xa.*;
          public class MyXid implements Xid
          {
           protected int formatId;
           protected byte gtrid[];
           protected byte bqual[];
           public MyXid()
           {
           }
           public MyXid(int formatId, byte gtrid[], byte bqual[])
           {
            this.formatId = formatId;
            this.gtrid = gtrid;
            this.bqual = bqual;
           }

           public int getFormatId()
           {
            return formatId;
           }

           public byte[] getBranchQualifier()
           {
            return bqual;
           }

           public byte[] getGlobalTransactionId()
           {
            return gtrid;
           }

          }
           其次,你需要?jiǎng)?chuàng)建一個(gè)你要使用的數(shù)據(jù)庫(kù)的數(shù)據(jù)源:

          public DataSource getDataSource()
           throws SQLException
           {
            SQLServerDataSource xaDS = new
            com.merant.datadirect.jdbcx.sqlserver.SQLServerDataSource();
            xaDS.setDataSourceName("SQLServer");
            xaDS.setServerName("server");
            xaDS.setPortNumber(1433);
            xaDS.setSelectMethod("cursor");
            return xaDS;
          }

            例1?這個(gè)例子是用“兩步提交協(xié)議”來(lái)提交一個(gè)事務(wù)分支:

          XADataSource xaDS;
          XAConnection xaCon;
          XAResource xaRes;
          Xid xid;
          Connection con;
          Statement stmt;
          int ret;
          xaDS = getDataSource();
          xaCon = xaDS.getXAConnection("jdbc_user", "jdbc_password");
          xaRes = xaCon.getXAResource();
          con = xaCon.getConnection();
          stmt = con.createStatement();
          xid = new MyXid(100, new byte[]{0x01}, new byte[]{0x02});
          try {
            xaRes.start(xid, XAResource.TMNOFLAGS);
            stmt.executeUpdate("insert into test_table values (100)");
            xaRes.end(xid, XAResource.TMSUCCESS);
            ret = xaRes.prepare(xid);
            if (ret == XAResource.XA_OK) {
              xaRes.commit(xid, false);
             }
          }
          catch (XAException e) {
           e.printStackTrace();
          }
          finally {
           stmt.close();
           con.close();
           xaCon.close();
          }
           當(dāng)然,實(shí)際過(guò)程中,我們不需要寫這些代碼,這些代碼是JTA最終的實(shí)現(xiàn)代碼。
          關(guān)于“兩步提交協(xié)議”,可以參看下面的文章:
          http://www.jspcn.net/htmlnews/11049371131251752.html

           http://www.vermicelli.pasta.cs.uit.no/ipv6/students/andrer/doc/html/node18.html


          選擇最好的方式
          用 JDBC API 進(jìn)事務(wù)界定來(lái)構(gòu)建 DAO 類的。這些 DAO 類可以總結(jié)如下:

          事務(wù)界定代碼嵌入在 DAO 類中。
          DAO 類使用 JDBC API 進(jìn)行事務(wù)界定。
          調(diào)用者不能界定事務(wù)。
          事務(wù)范圍局限于單個(gè) JDBC 連接。
          JDBC 事務(wù)并不總是適合復(fù)雜的企業(yè)應(yīng)用程序。如果您的事務(wù)要跨越多個(gè) DAO 或者多個(gè)數(shù)據(jù)庫(kù),那么下列實(shí)現(xiàn)策略也許更合適:

          事務(wù)用 JTA 界定。
          事務(wù)界定代碼從 DAO 中分離出來(lái)。
          調(diào)用者負(fù)責(zé)界定事務(wù)。
          DAO 加入一個(gè)全局事務(wù)。
          JDBC 方式由于其簡(jiǎn)單性而具有吸引力,JTA 方式提供了更大的靈活性。您所選擇的實(shí)現(xiàn)將取決于應(yīng)用程序的特定需求。
          XADataSource例子:
          <?xml version="1.0" encoding="UTF-8"?>

          <!-- ===================================================================== -->
          <!--    -->
          <!--  JBoss Server Configuration    -->
          <!-- Thanks to Horia Muntean <horia@bvb.ro>   -->
          <!-- ===================================================================== -->

          <!-- $Id: db2-xa-ds.xml,v 1.1.2.1 2003/05/30 18:25:57 d_jencks Exp $ -->


          <datasources>
             <!--
                 XADatasource for DB2 V8.1 (app driver)
                 copy $db2_install_dir/java/db2java.zip into $jboss_install_dir/server/default/lib
             -->

             <xa-datasource>
               <jndi-name>DB2XADS</jndi-name>
               <xa-datasource-class>COM.ibm.db2.jdbc.DB2XADataSource</xa-datasource-class>
               <xa-datasource-property name="DatabaseName">yout_database_name</xa-datasource-property>
               <xa-datasource-property name="User">your_user</xa-datasource-property>
               <xa-datasource-property name="Password">your_password</xa-datasource-property>
             </xa-datasource>
          </datasources>

          引用:
           http://www.jspcn.net/htmlnews/11049371131251752.html
          http://www-128.ibm.com/developerworks/cn/java/j-dao/
          http://www.vermicelli.pasta.cs.uit.no/ipv6/students/andrer/doc/html/node18.html

           

          posted on 2006-06-15 15:53 binge 閱讀(5217) 評(píng)論(1)  編輯  收藏 所屬分類: J2EE

          評(píng)論

          # re: JTA和JDBC事務(wù)[未登錄]  回復(fù)  更多評(píng)論   

          在jdbc中,可以通過(guò)調(diào)用setAutoCommit(false)來(lái)禁止自動(dòng)提交。之后就可以把多個(gè)數(shù)據(jù)庫(kù)操作的表達(dá)式作為一個(gè)事務(wù),在操作完成后調(diào)用commit()來(lái)進(jìn)行整體提交,倘若其中一個(gè)表達(dá)式操作失敗,都不會(huì)執(zhí)行到commit(),并且將產(chǎn)生響應(yīng)的異常;

          筆誤了吧?“之后就可以把多個(gè)數(shù)據(jù)庫(kù)操作的表達(dá)式作為一個(gè)事務(wù)”,JDBC開啟事務(wù)是一個(gè)connection對(duì)應(yīng)一個(gè)吧?多個(gè)數(shù)據(jù)庫(kù)操作就是多個(gè)connection=多個(gè)事務(wù),怎么做到當(dāng)做同一個(gè)呢。
          2014-01-24 17:16 | test
          主站蜘蛛池模板: 扎赉特旗| 黄骅市| 东辽县| 德阳市| 海南省| 垦利县| 丽江市| 商洛市| 时尚| 深州市| 清水河县| 酒泉市| 吉木乃县| 盖州市| 巴马| 杂多县| 青海省| 深圳市| 穆棱市| 海晏县| 什邡市| 绥中县| 定日县| 荥经县| 土默特右旗| 布拖县| 饶河县| 南部县| 砀山县| 陆丰市| 潞城市| 海盐县| 新野县| 鹤庆县| 柏乡县| 鄂伦春自治旗| 闵行区| 巴彦县| 金华市| 南通市| 长宁区|