<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    魚躍于淵

    First know how, Second know why !
    posts - 0, comments - 1, trackbacks - 0, articles - 49

    Java 處理事務精要

    Posted on 2008-09-20 09:08 魚躍于淵 閱讀(125) 評論(0)  編輯  收藏 所屬分類: 精品網摘

     

    Java 處理事務精要

        

    [摘要] 有一個訂單庫存管理系統,每一次生成訂單的同時我們都要消減庫存。通常來說訂單和庫存在數據庫里是分兩張表來保存的:訂單表,庫存表。每一次追加一個訂單實際上需要兩步操作:在訂單表中插入一條數據,同時修改庫存的數據。
    [關鍵字]
    Java 事務
      簡單事務的概念

      我不想從原理上說明什么是事務,應為那太枯燥了。我只想從一個簡單的例子來說明什么是事務。

      例如我們有一個訂單庫存管理系統,每一次生成訂單的同時我們都要消減庫存。通常來說訂單和庫存在數據庫里是分兩張表來保存的:訂單表,庫存表。每一次我們追加一個訂單實際上需要兩步操作:在訂單表中插入一條數據,同時修改庫存的數據。

      這樣問題來了,例如我們需要一個單位為10的訂單,庫存中有30件,理想的操作是我們在訂單表中插入了一條單位為10的訂單,之后將庫存表中的數據修改為20。但是有些時候事情并不是總是按照你的想法發生,例如:在你修改庫存的時候,數據庫突然由于莫名其妙的原因無法連接上了。也就是說庫存更新失敗了。但是訂單已經產生了,那么怎么辦呢?沒辦法,只有手動的修改。所以最好的方式是將訂單插入的操作和庫存修改的操作綁定在一起,必須同時成功或者什么都不做。這就是事務。

      Java如何處理事務呢?

      我們從java.sql.Connection說起,Connection表示了一個和數據庫的鏈接,可以通過Connection來對數據庫操作。在通常情況是Connection的屬性是自動提交的,也就是說每次的操作真的更新了數據庫,真的無法回退了。針對上述的例子,一旦庫存更新失敗了,訂單無法回退,因為訂單真的插入到了數據庫中。這并不是我們希望的。

      我們希望的是:看起來成功了,但是沒有真的操作數據庫,知道我想讓他真的發生。可以通過Connection的setAutoCommit(false)讓Connection不自動提交你的數據,除非你真的想提交。那么如何讓操作真的發生呢?可以使用Connection的commit方法。如何讓操作回退呢?使用rollback方法。

      例如:

      try{

      Connection conn = getConnection(); // 不管如何我們得到了鏈接

      conn.setAutoCommit(false);

      // 插入訂單

      // 修改庫存

      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();

      // 插入訂單

      // 修改庫存

      ut.commit(); // 成功的情況下,提交更新。

      } catch(SQLException ex) {

      ut.rollback(); // 失敗的情況下,回滾所有的操作

      } finally {

      conn.close();

      }

      如何獲取UserTransaction呢?可以使用如下方法

      UserTransaction tx = (UserTransaction)

      ctx.lookup("jndi/UserTransaction");

    主站蜘蛛池模板: 亚洲国产香蕉碰碰人人| 日韩免费观看视频| 久久久亚洲欧洲日产国码农村| 一区二区三区免费视频观看| 亚洲精品456播放| 一区二区三区精品高清视频免费在线播放 | 国产成人一区二区三区免费视频 | 国产禁女女网站免费看| 精品亚洲456在线播放| 一级免费黄色毛片| 亚洲av成人一区二区三区在线观看| 亚洲av永久无码精品网址| 日韩免费一区二区三区| 欧洲亚洲综合一区二区三区 | 亚洲无av在线中文字幕| 美女被cao网站免费看在线看| 夜夜嘿视频免费看| 亚洲a∨无码一区二区| 亚洲成a人片在线观看久| 亚洲卡一卡2卡三卡4麻豆| a级男女仿爱免费视频| 日本无吗免费一二区| 全部在线播放免费毛片| 永久亚洲成a人片777777| 亚洲av日韩av永久无码电影| 四虎永久免费地址在线网站| 亚洲H在线播放在线观看H| 亚洲男人天堂影院| 国产亚洲一区二区三区在线不卡 | 曰批免费视频播放免费| 色播精品免费小视频| 亚洲av无码专区国产乱码在线观看| 亚洲尹人香蕉网在线视颅| 深夜特黄a级毛片免费播放| 人妻仑乱A级毛片免费看| 亚洲天堂免费在线| 亚洲高清国产拍精品青青草原| 亚洲日韩看片无码电影| 国产激情免费视频在线观看| 亚洲人成网站18禁止一区| 中国内地毛片免费高清|