您好,登錄后才能下訂單哦!
進入主題之前,先來了解一下Spring事務,都有哪些內容:
Spring事務包含對分布式事務和單機事務的支持,我們用的比較多的是單機事務,也就是只操作一個數據庫的事務。
單機事務,按照用法分,又可以分為編程式事務模型(TransactionTemplate)和聲明式事務模型(@Transactional注解),后者可以理解為 aop + 編程式事務模型。
編程式事務模型里面涉及到很多知識點,比如統一事務模型、事務傳播級別、事務隔離級別等。
我們今天要講的是其中一點,統一事務模型。
希望這次的分享能夠讓大家,對Spring事務有一個整體性的認識。
Spring的統一事務模型,解決的一個核心問題,就是不管你用的是什么數據訪問方式,Hibernate、MyBatis抑或是JDBC,你的Service層的代碼都是一樣的,不需要做任何變動。
使用@Transactional注解的,相信大家都用過,而且由于注解的實現比較隱晦,不利于我們理解原理,這里就不演示。
下面介紹編程式事務模型,TransactionTemplate:
不管后面你的Dao實現如何變化,上面這一段Service代碼都無需修改,而且依舊可以保持事務的邏輯。
Spring是怎么做到的呢?
有人說,是模板模式。
點開TransactionTemplate,的確是封裝了事務操作的“套路”:
但是細看就會發現,這和我們傳統的template模式還有點不同。
傳統的template,一般會有一個抽象類,抽象類里封裝了一系列有規律的套路,然后有些套路是抽象的,需要你自己去實現:
而TransactionTemplate,它已經是一個具體的類,無需實現任何方法,拿來即用。
但仔細看,就會發現里面有一個叫transactionManager的家伙,出鏡率特別高,它幫TransactionTemplate做了很多事情。
點開一看,這家伙是個叫PlatformTransactionManager的接口:
恍然大悟,你只需給TransactionTemplate傳一個PlatformTransactionManager的具體實現,也就是告訴TransactionTemplate,事務創建、提交、回滾的具體策略,它就可以按照自己的那套流程,完成事務的操作。
TransactionTemplate,其實是模板+策略的雙劍合璧。
針對不同的廠商,只需要提供不同的PlatformTransactionManager實現即可。
比如對于MyBatis,就用DataSourceTxManager,對于Hibernate,就用HibernateTxManager:
不同廠商在實現的時候,按照自己對應的事務操作方式,進行實現即可。
比如DataSourceTxManager,創建事務的時候,new了一個自己的事務對象,最后返回一個Object類型,在commit的時候,再把這個Object,強轉成自己的事務對象:
HibernateTxManager也是如此:
我們在使用的時候,只需要通過Spring IOC,告訴Spring,要注入哪個TransactionManager,要使用哪種策略即可:
了解完Spring是如何實現統一的事務模型,不知道你是否也有疑問:既然是事務,那就要保證事務里的所有dao操作,都要使用同一個數據庫連接進行操作,但是我們在寫代碼的時候,并不需要給dao傳入connection對象:
Spring又是怎么做到的?
答案是ThreadLocal。
通過ThreadLocal,在同一個線程中共享connection。
這很好理解,關鍵是,這是一個什么樣的ThreadLocal?填空題。
也許你和我一開始想的一樣,認為這里面放到就是connection對象。
直接放connection對象會有一個問題,那就是當你事務里面,涉及到對多個數據庫進行操作時,后面的操作取到的,就都是第一個數據庫操作放進去的connection:
如上圖,假設deleteAll操作的是db1,那么它創建了針對db1的connection,然后放進ThreadLocal,然后save,本來是想操作db2的,結果它從threadLocal里拿到的,卻是剛剛deleteAll時,放進去的操作db1的connection,卒。
實際上,Spring在ThreadLocal里頭,放的是一個Map。key是dataSource,value才是connection.
Spring是支持在事務里面新開一個事務的,最簡單的方式就是使用聲明式事務模型:
然而,按照之前的理論,如果每次都是從ThreadLocal里去獲取connection,那么永遠拿到的都是舊的事務,不會創建新事務。
Spring又是如何實現新開事務的呢?
很簡單,鏈表。
一開始,舊事務綁定在當前線程:
當需要新開事務時,先將原來的事務解綁:
然后new一個新的事務:
接著將新的事務指向舊事務:
最后將新事務綁定到當前線程:
之所以需要將新事務指向舊事務,形成一個事務鏈,是因為新事務在提交或者回滾之后,還需要恢復舊事務:
這一塊邏輯對應的代碼:
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。