日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

spring手动控制事务开启_“上帝视角”图解Spring事务的传播机制原理

發布時間:2025/3/19 javascript 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 spring手动控制事务开启_“上帝视角”图解Spring事务的传播机制原理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉載:https://mp.weixin.qq.com/s/odP1DKgRtXsCcAKxwGahug

數據庫事務的“抓手”
數據庫的事務功能已經由數據庫自身實現,它留給用戶的就是三個指令:開啟事務、提交事務和回滾事務。
開啟事務一般是start transaction或begin transaction。提交事務通常都是commit。回滾事務通常都是rollback。
數據庫通常都有自動開啟事務和自動提交事務的開關,打開后,事務就會自動的開啟和提交或回滾。這樣用戶就無感知了。JDBC的事務“抓手”
JDBC實現了訪問數據庫的協議,可以認為是對一些指令的封裝,當然也包括這些事務指令。它們都被做到了java.sql.Connection這個接口里。
它代表到數據庫的一個連接,當這個連接建立好后,默認事務就已經打開了,而且默認情況下執行完一個SQL語句后事務也是自動提交的。
可以通過下面這個API進行檢測:
boolean getAutoCommit();
通常情況下,我們都不希望事務是一句一提交,而是要執行若干個SQL語句后一次性提交,此時我們就需要改變這種自動提交的行為。
可以通過下面這個API進行設置:
void setAutoCommit(boolean autoCommit);
當我們禁用掉自動提交之后,一定要記得自己手動提交事務,否則結果可想而知。當然,需要回滾的時候也要記得手動回滾。
可以通過下面這個API提交事務:
void commit();
可以通過下面這個API回滾事務:
void rollback();
這樣我們就可以在Java代碼級別來控制事務的行為了。同時我們也應該認識到,在Java代碼級別事務是和Connecton的實例對象綁在一起的。
換句話說,只有在同一個Connection對象上執行的SQL語句才會在同一個事務里。在不同的Connection對象上執行的SQL語句永遠不會在同一個事務里。
更精確地說,后者構成的是分布式事務,前者通常稱為本地事務。當然,分布式事務有屬于自己的解決方案,只是不能再使用本地事務了。備注:以上這些其實都是基本常識,只是現在的ORM框架太牛了,導致很多年輕的碼農都沒機會再接觸這些了。Spring的事務“抓手”
Spring通過使用@Transactional注解實現了聲明式事務,并且可以通過設置Propagation屬性來影響事務的傳播特性。
事務的傳播特性其實就是指,Service層的若干方法在互相調用交織在一起的時候,究竟哪些方法的代碼是在同一個事務里執行,哪些方法的代碼不是。
通過前面的分析可知,在同一個事務里執行的方法代碼背后必須使用的是同一個Connection對象,當事務切換時,必須要切換背后的Connection對象為對應的另一個。
因此,當執行流程進入/退出不同的方法時,Spring根據方法上注解的傳播特性,在背后對應的進行Connection對象的切換,也包括新建Connection對象,提交或回滾事務等。
我們知道,在寫Service層方法或Mapper層方法時,根本接觸不到Connection對象,所以它更不可能明目張膽的以參數的方式傳來傳去,只能在背地里暗箱操作。
由于這些互相交織的方法代碼最終都是在同一個線程里運行的,所以借助線程的ThreadLocal來實現背后的操作是最適合的。
只需在方法調用的入口/出口來新建/切換Connection對象,并提交/回滾Connection對象上的事務即可。Spring事務的傳播特性原理
Spring事務是通過代理來實現的,通常是通過CGLIB操作字節碼來生成子類,因為要動態加入開啟/提交事務的這些代碼。
下面通過一個例子來說明,有四個方法及其對應的傳播特性:
方法一,傳播特性為REQUIRED:
void method1();
方法二,傳播特性為REQUIRED:
void method2();
方法三,傳播特性為REQUIRES_NEW:
void method3();
方法四,傳播特性為REQUIRED:
void method4();
假設它們之間的調用關系是,在方法一里依次調用方法二三四:
void method1() {
method2();
method3();
method4();
}
可以使用下面這個圖來表示,圖01:


那么經過Spring生成代理后,會重寫每個方法,并在原來的每個方法前面開啟事務,方法后面提交/回滾事務。
等效的偽代碼如下:
beginTx();
void method1() {
beginTx();
method2();
commit/rollbackTx();
beginTx();
method3();
commit/rollbackTx();
beginTx();
method4();
commit/rollbackTx();
}
commit/rollbackTx();
可以使用下面這個圖來表示,圖02:


其中紅色的向上箭頭對應于beginTx()操作,藍色的向下箭頭對應于commit/rollbackTx()操作。
下面就來看看具體的執行過程:
一、執行方法一的開啟事務,圖03:


由于方法一要求有事務,此時線程中沒有事務,于是就開啟一個新的事務,即創建一個新的Connection對象并綁定到線程的ThreadLocal。
二、進入方法一開始執行,圖04:


三、執行方法二的開啟事務,圖05:


由于方法二要求有事務,此時線程中已經有事務了,因此直接參與/使用這個事務即可。
四、進入方法二開始執行,圖06:


五、方法二完畢執行提交事務,圖07:


由于該事務并非方法二新建的,它只是參與而已,所以它沒有資格提交事務,因此實際并不提交事務。
六、方法二結束后又回到方法一里執行,圖08:


七、執行方法三的開啟事務,圖09:


由于方法三要求新的事物,所以新建一個事務,并把當前的現有事務掛起,使當前線程使用新事務。
即新建一個Connection對象,把當前現有Connection對象與線程的ThreadLocal解綁,把新的Connection對象綁定到線程的ThreadLocal。
那原來的那個Connection對象呢?當然是存儲起來了,存儲的形式是依附于新的Connection對象,即和新的對象關聯一下。
八、進入方法三開始執行,圖10:


可以看到,原來的事務相當于暫存在新的事務里。注意,這種說法只是一個形象的比喻。
九、方法三完畢執行提交事務,圖11:


由于這個事務是個新建事務,即是方法三創建的而非參與的,所以有權提交,所以事務就真的提交了。
十、方法三結束后又回到方法一里執行,圖12:


方法三的事務完成了,但是它里面暫存了方法一的事務,于是把它重新恢復到線程里去。
十一、執行方法四的開啟事務,圖13:


由于方法四要求有事務,此時線程中已經有事務了,因此直接參與/使用這個事務即可。
十二、進入方法四開始執行,圖14:


十三、方法四完畢執行提交事務,圖15:


由于該事務并非方法四新建的,它只是參與而已,所以它沒有資格提交事務,因此實際并不提交事務。
十四、方法四結束后又回到方法一里執行,圖16:


十五、方法一完畢執行提交事務,圖17:


由于這個事務是個新建事務,即是方法一創建的而非參與的,所以有權提交,所以事務就真的提交了。
十六、所有事務完成,只剩一個空線程,圖18:

方法一的事務完成了,由于它里面沒有暫存其它事務,所以沒有事務了,因此最后只剩一個空線程。說明:這只是傳播特性的實現原理解說,所以比較簡單,實際代碼實現要考慮很多事情,因此會復雜很多。

推薦閱讀:

太好了!某騰花399¥買來史上最全MySQL數據庫視頻教程(2020Java面試必備底層)

Spring源碼實戰全集,資深架構師帶你搞懂Spring源碼底層從入門到入墳

阿里P9架構師120分鐘帶你掌握線程池,不在為線程而煩惱_

面試美團被JVM慘虐?阿里P9架構師用500分鐘把JVM從入門講到實戰#合集

全B站有史以來最全阿里、騰訊、字節、美團、谷歌算法面試題合集_

總結

以上是生活随笔為你收集整理的spring手动控制事务开启_“上帝视角”图解Spring事务的传播机制原理的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。