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,現在我明白了  回復  更多評論
            
          主站蜘蛛池模板: 涞水县| 清水县| 高碑店市| 武城县| 达孜县| 明水县| 兴国县| 宁都县| 富锦市| 通河县| 二连浩特市| 水富县| 昭觉县| 景德镇市| 金寨县| 邓州市| 武邑县| 剑河县| 射阳县| 高台县| 常德市| 法库县| 四川省| 武乡县| 云梦县| 凤庆县| 伊吾县| 承德市| 六安市| 安龙县| 太保市| 卓资县| 浮梁县| 许昌县| 湘阴县| 湖南省| 南漳县| 郑州市| 鱼台县| 深圳市| 桦甸市|