byterat

            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            54 隨筆 :: 0 文章 :: 15 評論 :: 0 Trackbacks

          spring事務(wù)探索

          原文出處:
          http://www.javaeye.com/topic/11190

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

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

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

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

          比如

          HibernateTransactionManager

          代碼

          ?

          1. protected ? void ?doCommit(DefaultTransactionStatus?status)?{ ??
          2. ????????HibernateTransactionObject?txObject?=?(HibernateTransactionObject)?status.getTransaction(); ??
          3. ???????? if ?(status.isDebug())?{ ??
          4. ????????????logger.debug( "Committing?Hibernate?transaction?on?session?[" ?+ ??
          5. ????????????????????txObject.getSessionHolder().getSession()?+? "]" ); ??
          6. ????????} ??
          7. ???????? try ?{ ??
          8. ????????????txObject.getSessionHolder().getTransaction().commit(); ??
          9. ????????} ??
          10. ... ??
          11. ??
          12. ????}??

          jdbc 的DataSourceTransactionManager

          代碼

          ?

          1. protected ? void ?doCommit(DefaultTransactionStatus?status)?{ ??
          2. ????????DataSourceTransactionObject?txObject?=?(DataSourceTransactionObject)?status.getTransaction(); ??
          3. ????????Connection?con?=?txObject.getConnectionHolder().getConnection(); ??
          4. ???????? if ?(status.isDebug())?{ ??
          5. ????????????logger.debug( "Committing?JDBC?transaction?on?connection?[" ?+?con?+? "]" ); ??
          6. ????????} ??
          7. ???????? try ?{ ??
          8. ????????????con.commit(); ??
          9. ????????} ??
          10. ????????... ??
          11. ????}??

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

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

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

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

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

          代碼

          ?

          1. DefaultTransactionDefinition?def?=? new ?DefaultTransactionDefinition() ??
          2. def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); ??
          3. ??
          4. TransactionStatus?status?=?transactionManager.getTransaction(def); ??
          5. ??
          6. try ?{ ??
          7. ???? //?execute?your?business?logic?here ??
          8. }? catch ?(MyException?ex)?{ ??
          9. ????transactionManager.rollback(status); ??
          10. ???? throw ?ex; ??
          11. } ??
          12. transactionManager.commit(status);??


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

          代碼

          ?

          1. public ?Object?execute(TransactionCallback?action)? throws ?TransactionException?{ ??
          2. ????????TransactionStatus?status?=? this .transactionManager.getTransaction( this ); ??
          3. ????????Object?result?=? null ; ??
          4. ???????? try ?{ ??
          5. ????????????result?=?action.doInTransaction(status); ??
          6. ????????} ??
          7. ???????? catch ?(RuntimeException?ex)?{ ??
          8. ???????????? //?transactional?code?threw?application?exception?->?rollback ??
          9. ????????????rollbackOnException(status,?ex); ??
          10. ???????????? throw ?ex; ??
          11. ????????} ??
          12. ???????? catch ?(Error?err)?{ ??
          13. ???????????? //?transactional?code?threw?error?->?rollback ??
          14. ????????????rollbackOnException(status,?err); ??
          15. ???????????? throw ?err; ??
          16. ????????} ??
          17. ???????? this .transactionManager.commit(status); ??
          18. ???????? return ?result; ??
          19. ????}??

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

          代碼

          ?

          1. private ? void ?rollbackOnException(TransactionStatus?status,?Throwable?ex)? throws ?TransactionException?{ ??
          2. ???????? if ?(logger.isDebugEnabled())?{ ??
          3. ????????????logger.debug( "Initiating?transaction?rollback?on?application?exception" ,?ex); ??
          4. ????????} ??
          5. ???????? try ?{ ??
          6. ???????????? this .transactionManager.rollback(status); ??
          7. ????????} ??
          8. ???????? catch ?(RuntimeException?ex2)?{ ??
          9. ????????????logger.error( "Application?exception?overridden?by?rollback?exception" ,?ex); ??
          10. ???????????? throw ?ex2; ??
          11. ????????} ??
          12. ???????? catch ?(Error?err)?{ ??
          13. ????????????logger.error( "Application?exception?overridden?by?rollback?error" ,?ex); ??
          14. ???????????? throw ?err; ??
          15. ????????} ??
          16. ????}??


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

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

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

          代碼

          ?

          1. public ?Object?invoke(MethodInvocation?invocation)? throws ?Throwable?{ ??
          2. ???????? //?Work?out?the?target?class:?may?be?null. ??
          3. ???????? //?The?TransactionAttributeSource?should?be?passed?the?target?class ??
          4. ???????? //?as?well?as?the?method,?which?may?be?from?an?interface ??
          5. ????????Class?targetClass?=?(invocation.getThis()?!=? null )???invocation.getThis().getClass()?:? null ; ??
          6. ???????? ??
          7. ???????? //?Create?transaction?if?necessary ??
          8. ????????TransactionInfo?txInfo?=?createTransactionIfNecessary(invocation.getMethod(),?targetClass); ??
          9. ??
          10. ????????Object?retVal?=? null ; ??
          11. ???????? try ?{ ??
          12. ???????????? //?This?is?an?around?advice. ??
          13. ???????????? //?Invoke?the?next?interceptor?in?the?chain. ??
          14. ???????????? //?This?will?normally?result?in?a?target?object?being?invoked. ??
          15. ????????????retVal?=?invocation.proceed(); ??
          16. ????????} ??
          17. ???????? catch ?(Throwable?ex)?{ ??
          18. ???????????? //?target?invocation?exception ??
          19. ????????????doCloseTransactionAfterThrowing(txInfo,?ex); ??
          20. ???????????? throw ?ex; ??
          21. ????????} ??
          22. ???????? finally ?{ ??
          23. ????????????doFinally(txInfo); ??
          24. ????????} ??
          25. ????????doCommitTransactionAfterReturning(txInfo); ??
          26. ??
          27. ???????? return ?retVal; ??
          28. ????}??


          萬變不離其宗。

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

          posted on 2007-03-05 14:45 比特鼠 閱讀(249) 評論(0)  編輯  收藏 所屬分類: Java Frameworks
          主站蜘蛛池模板: 昌乐县| 诸暨市| 邻水| 林口县| 东丽区| 剑河县| 曲松县| 河曲县| 全州县| 舟山市| 莱芜市| 凤冈县| 南郑县| 巍山| 洮南市| 惠安县| 平定县| 云林县| 揭西县| 盘山县| 盐山县| 南充市| 枣庄市| 安国市| 沿河| 桃源县| 迁安市| 遂川县| 同心县| 固安县| 桓台县| 临猗县| 肇源县| 天等县| 宣化县| 肥乡县| 松原市| 山西省| 深州市| 凉山| 青神县|