yxhxj2006

          常用鏈接

          統計

          最新評論

          最簡單的Java處理事務

          用一個簡單的例子來說明Java處理事務:
          我們用銀行轉賬的時候可以簡單的看成是兩步操作--將錢從A賬戶轉出和將錢轉到B賬戶。問題來了,如果我從A賬戶轉出之后,突然無法連接數據庫了,這樣錢就不能轉到B賬戶了,可是A的錢已經沒了。所以我們應該把這兩步看成是一個整體,要么同時成功,要么什么都不做。這就是事務了。
           
          Java中是如何處理事務的呢?
          我們從java.sql.Connection說起,Connection表示了一個和數據庫的鏈接,可以通過Connection來對數據庫操作。在通常情況是Connection的屬性是自動提交的,也就是說每次的操作真的更新了數據庫,真的無法回退了。針對上述的例子,一旦A賬戶的錢轉出了,即對數據庫進行了更新操作了,但是錢并沒有轉到B的賬戶,這筆錢就白白“不見”了。這并不是我們希望的。 
              我們希望的是:看起來成功了,但是沒有真的操作數據庫,知道我想讓他真的發生。可以通過Connection的setAutoCommit(false)讓Connection不自動提交你的數據,除非你真的想提交。那么如何讓操作真的發生呢?可以使用Connection的commit方法。如何讓操作回退呢?使用rollback方法。
          例如: 
            try{ 
            Connection conn = getConnection(); // 不管如何我們得到了鏈接 
            conn.setAutoCommit(false); 
            // A賬戶轉出
            // B賬戶轉入
            conn.commit(); // 成功的情況下,提交更新。 
            } catch(SQLException ex) { 
            conn.rollback(); // 失敗的情況下,回滾所有的操作 
            } finally { 
            conn.close();
            } 
              這里有一點非常重要,事務是基于數據庫鏈接的。所以在但數據庫的情況下,事務操作很簡單。 
            那么如果表分布在兩個不同的數據庫中呢? 
            例如訂單表在訂單庫中,庫存表在庫存庫中,那么我們如何處理這樣的事務呢? 
            需要注意,提交也可以遇到錯誤呀! 
            try{ 
            Connection conn1 = getConnection1(); 
            Connection conn2 = getConnection2(); 
            // 基于conn1做更新操作 
            // 基于conn2做更新操作 
            try{ 
            conn1.commit() 
            } catch(SQLExcetion ) { 
            conn1.rollback(); 
            } 
            try { 
            conn2.commit(); 
            } catch(SQLException ) { 
            conn2.rollbakc(); 
            // 保證務必將剛才的更新還原回來。 
            } 
            } catch(SQLException ex) { 
            // 如果更新失敗,conn1.rollback 
            // 如果更新失敗,conn1.rollback && conn2.rollback 
            } finally { 
            conn1.close(); 
            conn2.close(); 
            } 
            看看上述的代碼就知道,其實操作非常的復雜,甚至:保證肯定還原剛才更新的賬戶根本無法保證。
          在上述情況下的事務可以稱之為分布式事務,通過上述的代碼中事務同時提交處理的部分我們可以得出,要想處理分布式事務,必須有獨立于數據庫的第三方的事務處理組件。 
            幸運的是通常情況下,JavaEE兼容的應用服務器,例如:Weblogic,Websphere,JBoss,Glassfish等都有這種分布式事務處理的組件。 

          如何使用應用服務器的分布式事務管理器處理分布式事務? 
            以galssfish為例 
            1 建立對應兩個數據庫的XA(javax.sql.XADataSource)類型的數據源。 
            2 使用UserTransaction來保證分布式事務。 
            try{ 
            Connection conn1 = datasource1.getConnection(); 
            Connection conn2 = datasource2.getConnection(); 
            UserTransaction ut = getUserTransaction(); 
            ut.begin(); 
            // A賬戶轉出
            // B賬戶轉入
            ut.commit(); // 成功的情況下,提交更新。 
            } catch(SQLException ex) { 
            ut.rollback(); // 失敗的情況下,回滾所有的操作 
            } finally { 
            conn.close(); 
            } 
            如何獲取UserTransaction呢?可以使用如下方法 
            UserTransaction tx = (UserTransaction) ctx.lookup("jndi/UserTransaction"); 

          posted on 2012-07-19 15:35 奮斗成就男人 閱讀(186) 評論(0)  編輯  收藏


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


          網站導航:
           
          主站蜘蛛池模板: 大渡口区| 连城县| 河南省| 阿尔山市| 永仁县| 洪泽县| 南雄市| 秦皇岛市| 北票市| 奉新县| 龙泉市| 巫溪县| 绥中县| 肇源县| 成武县| 广昌县| 漳浦县| 分宜县| 淮南市| 监利县| 邹城市| 南岸区| 大厂| 贵港市| 冷水江市| 乌拉特前旗| 陕西省| 遵义市| 定陶县| 藁城市| 佛冈县| 淮阳县| 繁峙县| 延安市| 霍山县| 伽师县| 泰兴市| 平舆县| 兴业县| 丹寨县| 高雄县|