kapok

          垃圾桶,嘿嘿,我藏的這么深你們還能找到啊,真牛!

            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            455 隨筆 :: 0 文章 :: 76 評(píng)論 :: 0 Trackbacks
          <2005年3月>
          272812345
          6789101112
          13141516171819
          20212223242526
          272829303112
          3456789

          常用鏈接

          留言簿(28)

          隨筆分類

          隨筆檔案

          Corba

          EAI

          Online Document

          Open Source

          Portal

          RSS Links

          Weblogic

          不錯(cuò)的鏈接

          工具集合

          數(shù)據(jù)倉(cāng)庫(kù)相關(guān)

          搜索

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          spring自建事務(wù)管理模塊。而且這個(gè)事務(wù)管理是一個(gè)抽象設(shè)計(jì),可以應(yīng)用到很多場(chǎng)合,包括普通的DataSource,jta,jms和hibernate上。

          要正確使用spring的事務(wù),首先需要了解spring在事務(wù)設(shè)計(jì)上的一些概念
          統(tǒng)觀spring事務(wù),圍繞著兩個(gè)核心PlatformTransactionManager和TransactionStatus

          PlatformTransactionManager直譯過來就是平臺(tái)相關(guān)事務(wù),這里的平臺(tái)指的是“事務(wù)源”,包括剛才我說的DataSource,jta等等。這些無一不是一個(gè)事務(wù)源。廣義的說,凡是可以完成事務(wù)性操作的對(duì)象,都可以設(shè)計(jì)出相對(duì)應(yīng)的PlatformTransactionManager,只要這個(gè)事務(wù)源支持commit,rollback和getTransaction語意。

          查看spring代碼,可以發(fā)現(xiàn)這些manager實(shí)現(xiàn)事務(wù),就是調(diào)用事務(wù)源的事務(wù)操作方法

          比如

          HibernateTransactionManager
          java代碼: 

          protected void doCommit(DefaultTransactionStatus status) {
                          HibernateTransactionObject txObject = (HibernateTransactionObject) status.getTransaction();
                          if (status.isDebug()) {
                                  logger.debug("Committing Hibernate transaction on session [" +
                                                  txObject.getSessionHolder().getSession() + "]");
                          }
                          try {
                                  txObject.getSessionHolder().getTransaction().commit();
                          }
          ...

                  }
           

           

          jdbc 的DataSourceTransactionManager
          java代碼: 

          protected void doCommit(DefaultTransactionStatus status) {
                          DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
                          Connection con = txObject.getConnectionHolder().getConnection();
                          if (status.isDebug()) {
                                  logger.debug("Committing JDBC transaction on connection [" + con + "]");
                          }
                          try {
                                  con.commit();
                          }
                          ...
                  }
           

           

          那么PlatformTransactionManager以什么依據(jù)處理事務(wù)呢?
          是TransactionStatus
          查看api發(fā)現(xiàn)這個(gè)接口有三個(gè)方法
          isNewTransaction() ,isRollbackOnly(),setRollbackOnly()
          PlatformTransactionManager就是根據(jù)前兩個(gè)方法決定是否要?jiǎng)?chuàng)建一個(gè)新事務(wù),是要遞交還是回滾。至于第三個(gè)方法是改變事務(wù)當(dāng)前狀態(tài)的,很多地方都要用到,偏偏PlatformTransactionManager自身好像不怎么用,畢竟事務(wù)狀態(tài)的改變是由程序員代碼決定的,不需要一個(gè)manager多管閑事。

          總結(jié)上面所說的,spring的事務(wù)由PlatformTransactionManager管理,manager最后調(diào)用事務(wù)源的方法來實(shí)現(xiàn)一個(gè)事務(wù)過程。而manager通過TransactionStatus 來決定如何實(shí)現(xiàn)。

          接下去說spring事務(wù)中的TransactionTemplate和TransactionInterceptor

          TransactionTemplate其實(shí)和spring中其他的template的作用類似,起到化簡(jiǎn)代碼的作用,不要被它那么長(zhǎng)的名字嚇倒了,事實(shí)上這個(gè)template并不是什么非常核心的對(duì)象。如果比較學(xué)究派的,可以去看看template設(shè)計(jì)模式,在此就不再對(duì)此贅述了。
          為什么要有TransactionTemplate?先來看看如果沒有TransactionTemplate,我們的代碼該怎么寫

          先來看看spring reference中的一段代碼
          java代碼: 

          DefaultTransactionDefinition def = new DefaultTransactionDefinition()
          def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);

          TransactionStatus status = transactionManager.getTransaction(def);

          try {
              // execute your business logic here
          } catch (MyException ex) {
              transactionManager.rollback(status);
              throw ex;
          }
          transactionManager.commit(status);
           

          這是直接使用transactionManager的例子,可以看到真正執(zhí)行business logic 的地方是在try當(dāng)中那段,前后的代碼都是為了完成事務(wù)管理的。如果每個(gè)business logic都要寫上那么一段,我肯定是瘋了。我們翻出TransactionTemplate的代碼看看他怎么化簡(jiǎn)了我們的代碼

          java代碼: 

          public Object execute(TransactionCallback action) throws TransactionException {
                          TransactionStatus status = this.transactionManager.getTransaction(this);
                          Object result = null;
                          try {
                                  result = action.doInTransaction(status);
                          }
                          catch (RuntimeException ex) {
                                  // transactional code threw application exception -> rollback
                                  rollbackOnException(status, ex);
                                  throw ex;
                          }
                          catch (Error err) {
                                  // transactional code threw error -> rollback
                                  rollbackOnException(status, err);
                                  throw err;
                          }
                          this.transactionManager.commit(status);
                          return result;
                  }
           


          同上面的代碼如出一轍,前后是事務(wù)處理代碼,當(dāng)中那段result = action.doInTransaction(status);是我們的應(yīng)用代碼。至于action是什么,全看各位的需要了。但是有一點(diǎn)要主要,如果利用TransactionTemplate,那么他不管你扔出什么異常都會(huì)回滾事務(wù),但是回滾的是哪個(gè)事務(wù)呢?繼續(xù)挖代碼
          java代碼: 

          private void rollbackOnException(TransactionStatus status, Throwable ex) throws TransactionException {
                          if (logger.isDebugEnabled()) {
                                  logger.debug("Initiating transaction rollback on application exception", ex);
                          }
                          try {
                                  this.transactionManager.rollback(status);
                          }
                          catch (RuntimeException ex2) {
                                  logger.error("Application exception overridden by rollback exception", ex);
                                  throw ex2;
                          }
                          catch (Error err) {
                                  logger.error("Application exception overridden by rollback error", ex);
                                  throw err;
                          }
                  }
           

          真相大白,是對(duì)template所持有的某個(gè)transactionManager進(jìn)行回滾。所以如果你的應(yīng)用代碼用的是事務(wù)源a的一些資源,比如到服務(wù)器a的一個(gè)datasource,但是你的transactionManager管理的是另一些資源,比如服務(wù)器b的一個(gè)datasource,代碼鐵定不會(huì)正常運(yùn)行

          特別是在一些多事務(wù)源的程序里,這點(diǎn)千萬不能搞錯(cuò)。如果多個(gè)事務(wù)源之間要完成全局事務(wù),還是老老實(shí)實(shí)用分布式事務(wù)管理服務(wù)吧(jta)

          那么TransactionInterceptor是干什么的?這個(gè)是spring 的聲明式事務(wù)的支持方式。因?yàn)橛肨ransactionTemplate要硬編碼,而且調(diào)整事務(wù)策略很麻煩(不是說不能調(diào)。舉個(gè)例子原來程序拋出異常A需要回滾,現(xiàn)在不需要要,我就可以把a(bǔ) catch吃掉。這時(shí)候template就不會(huì)回滾了。但是每次調(diào)整都要重寫編碼。)而用TransactionInterceptor就可以將這些調(diào)整寫在配置中。我們?cè)賮硗赥ransactionInterceptor的代碼

          java代碼: 

          public Object invoke(MethodInvocation invocation) throws Throwable {
                          // Work out the target class: may be null.
                          // The TransactionAttributeSource should be passed the target class
                          // as well as the method, which may be from an interface
                          Class targetClass = (invocation.getThis() != null) ? invocation.getThis().getClass() : null;
                         
                          // Create transaction if necessary
                          TransactionInfo txInfo = createTransactionIfNecessary(invocation.getMethod(), targetClass);

                          Object retVal = null;
                          try {
                                  // This is an around advice.
                                  // Invoke the next interceptor in the chain.
                                  // This will normally result in a target object being invoked.
                                  retVal = invocation.proceed();
                          }
                          catch (Throwable ex) {
                                  // target invocation exception
                                  doCloseTransactionAfterThrowing(txInfo, ex);
                                  throw ex;
                          }
                          finally {
                                  doFinally(txInfo);
                          }
                          doCommitTransactionAfterReturning(txInfo);

                          return retVal;
                  }
           

          萬變不離其宗。

          所以使用spring的事務(wù)管理需要作這些事
          1,設(shè)置好事務(wù)源,比如DataSource,hibernate的session。如果有多個(gè)事務(wù)源要考慮他們之間是否有全局事務(wù),如果有,老老實(shí)實(shí)用jta,否則就需要自己寫一個(gè)manager了
          2,設(shè)置manager,根據(jù)你的事務(wù)源選擇對(duì)應(yīng)的PlatformTransactionManager
          3,選擇實(shí)現(xiàn)事物的方式,用template還是interceptor。用template代碼直觀點(diǎn),但是template所管轄的manager和你應(yīng)用代碼所用的事務(wù)源要一致。如果用interceptor千萬注意,一定要調(diào)用interceptor那個(gè)bean,而不是原始的那個(gè)target。在壇子上我已經(jīng)看到至少有兩個(gè)朋友說spring事物不起作用,從配置和代碼上看都正確,這時(shí)要好好查查,調(diào)用的bean是哪一個(gè)。
          4,這個(gè)是設(shè)計(jì)問題了,推薦事務(wù)處于一個(gè)較高層次,比如service上的某個(gè)函數(shù),而底層的dao可以不考慮事務(wù),否則可能會(huì)出現(xiàn)事務(wù)嵌套,增加程序復(fù)雜度。

          posted on 2005-03-16 11:50 笨笨 閱讀(680) 評(píng)論(0)  編輯  收藏 所屬分類: HibernateAndSpringALL
          主站蜘蛛池模板: 桦川县| 长顺县| 石狮市| 黄平县| 普兰县| 康平县| 灵川县| 察雅县| 汉沽区| 石楼县| 周宁县| 利津县| 酒泉市| 比如县| 吴堡县| 高雄市| 普洱| 宁蒗| 郁南县| 澄迈县| 双柏县| 孟津县| 财经| 溆浦县| 长泰县| 海门市| 多伦县| 浦北县| 梨树县| 宣威市| 安福县| 名山县| 资溪县| 马龙县| 榆社县| 牙克石市| 营山县| 黔西| 东丽区| 科技| 建昌县|