zhyiwww
          用平實的筆,記錄編程路上的點點滴滴………
          posts - 536,comments - 394,trackbacks - 0
          通常我們會把事務處理放在業務層。

          [1]引子

          比如:
          業務邏輯方法

          public A bussinessMethod(){

             DaoA   a = new DaoA();
             a.udpate();

             DaoB  b = new DaoB();
             b.update;

          }

          假設,上面的事務是自動提交的。
          那么,我們就可以什么不考慮。但是有一個問題,創建DAO對象的時候兩個對象用的是不同的Connection對象。

          再假定我們的取得連接的代碼是

              public Connection getConnection(String username, String password)
                      throws SQLException {
                  Connection con = DriverManager
                          .getConnection(conStr, username, password);
                  return con;
              }

          這個方法的一個調用。

          那么如果,我們需要自己控制事務的開始和結束。
          如何控制呢。
          也許又有了新的方法


          public A bussinessMethod(){

             DaoA   a = new DaoA();
             a.beginTx();
             a.udpate();
             a.endTx();
             a.close();

             DaoB  b = new DaoB();
             b.beginTx();
             b.update;
             b.endTx();
             b.close();
          }

          這樣我們就控制了事務,并且我們也只有這樣才能實現,因為,不同的DAO取得的是不同的Connection對象。

          [2]問題
          那么怎么才能實現兩個或多個DAO用同一個事務來控制呢?

          首先就要解決一個根本問題,我們在一個事務中,不同的DAO取得的是同一個Connection,這個要怎么實現呢。我們想到了TheadLocal.

          [3]方案
          因為當一個業務邏輯要對多個DAO進行處理的時候,此操作屬于同一個線程內。所以,我們希望能把此Connection放在線程內,或者和線程有關聯。
          第一個方案,可以用Map來使現。
          就是Map<Thread,Connection>
          但是這個map維護起來比較麻煩,如果一直put的話,那么這個map隨著系統的運行就會越來越大。

          第二個方案,就是用ThreadLocal
          在任何一個線程內都可以用ThreadLocal來保存一個變量的copy,這樣,如果此對象存在,就可以直接取用。
          如果把Connection存在ThreadLocal也一樣。

          所以,在同一個線程內,就可以保證取得到的是同一個Connection.


          [4]實現
          代碼

              private static ThreadLocal<Connection> localCon = new ThreadLocal<Connection>();

              public final static Connection getConnection() throws SQLException {

                 
                  Connection con = localCon.get();
                 
                  if(con==null||con.isClosed()){

                      con = new OracleJdbcDatasource().getConnection();
                     
                      localCon.set(con);
                  }
                 
                  return con;
              }


          這樣就實現了上面的問題。


          [5]新的事務管理

          public A bussinessMethod(){

             DaoA   a = new DaoA();
             DaoB  b = new DaoB();

             a.beginTx();
             a.udpate();

             b.beginTx();
             b.update;

             a.endTx();
             a.close();

          //   b.endTx();
          //   b.close();

          能實現一樣的效果
            
          }


          上面的黑體部分,就可以實現對事務的統一管理。

          [6]改進

          上面的方法給人的感覺有點別扭,但是卻能實現事務的統一管理。

          我還要繼續改進。








          |----------------------------------------------------------------------------------------|
                                     版權聲明  版權所有 @zhyiwww
                      引用請注明來源 http://www.aygfsteel.com/zhyiwww   
          |----------------------------------------------------------------------------------------|
          posted on 2010-02-11 15:34 zhyiwww 閱讀(1876) 評論(2)  編輯  收藏 所屬分類: j2ee

          FeedBack:
          # re: 事務管理與ThreadLocal
          2010-02-11 17:07 | Evan Wu
          兩個方法使用同一個事務,最好還是把它們合二為一。
          ps: Hibernate中的Connection就是用的ThreadLocal  回復  更多評論
            
          # re: 事務管理與ThreadLocal
          2010-02-12 10:02 | zhyiwww
          曾經,我也用hibernate的sessionFactory創建session,卻不知道為什么要用threadlocal,現在我明白了  回復  更多評論
            
          主站蜘蛛池模板: 岫岩| 思南县| 桃江县| 墨玉县| 鸡泽县| 荔浦县| 越西县| 喜德县| 沐川县| 内黄县| 招远市| 图们市| 慈溪市| 久治县| 安岳县| 通化市| 股票| 龙口市| 和静县| 无锡市| 刚察县| 扎鲁特旗| 门源| 海伦市| 大余县| 景泰县| 鹿泉市| 黄冈市| 清水县| 兰州市| 金山区| 栾川县| 定结县| 丁青县| 托里县| 琼海市| 蓝山县| 新巴尔虎右旗| 洪江市| 阿巴嘎旗| 海城市|