日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

瀏覽:97日期:2023-07-14 18:27:58
1 前言

很多需要使用事務的場景,都只是在方法上直接添加個@Transactional注解

關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

但是,你以為這真的夠了嗎?

事務如果未達到完美效果,在開發和測試階段都難以被發現,因為你難以考慮到太多意外場景。但當業務數據量發展,就可能導致大量數據不一致的問題,就會造成前人栽樹后人踩坑,需要大量人力排查解決問題和修復數據。

2 如何確認Spring事務生效了?

使用@Transactional一鍵開啟聲明式事務, 這就真的事務生效了?過于信任框架總有“意外驚喜”。來看如下案例

領域層 實體

關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

領域服務

createUserError1調用private方法

關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

createUserPrivate,被@Transactional注解。當傳入的用戶名包含test則拋異常,讓用戶的創建操作失敗

關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

getUserCount

關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

用戶接口層

調用UserService#createUserError1

關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

測試結果即便用戶名不合法,用戶也能創建成功。刷新瀏覽器,多次發現有十幾個的非法用戶注冊。 @Transactional生效原則 public方法

除非特殊配置(比如使用AspectJ靜態織入實現AOP),@Transactional必須定義在public方法才生效。

因為Spring的AOP,private方法無法被代理到,自然也無法動態增強事務處理邏輯。

那簡單,把createUserPrivate方法改為public不就行了。但發現事務依舊未生效

必須通過代理過的類從外部調用目標方法

要調用增強過的方法必然是調用代理后的對象。嘗試修改UserService,注入一個self,然后再通過self實例調用標記有 @Transactional 注解的createUserPublic方法。設置斷點可以看到,self是由Spring通過CGLIB方式增強過的類:

關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

CGLIB通過繼承實現代理類,private方法在子類不可見,所以無法進行事務增強。而this指針代表調用對象本身,Spring不可能注入this,所以通過this訪問方法必然不是代理。把this改為self,這時即可驗證事務生效:非法的用戶注冊操作可回滾。

雖然在UserDomainService內部注入自己調用自己的createUserPublic可正確實現事務,但這不符常規。更合理的實現方式是,讓Controller直接調用之前定義的UserService的createUserPublic方法。

關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

this/self/Controller調用UserDomainService

關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

this自調用

無法走到Spring代理類

后兩種

調用的Spring注入的UserService,通過代理調用才有機會對createUserPublic方法進行動態增強。

推薦開發時打開Debug日志以了解Spring事務實現的細節。比如JPA數據庫訪問,開啟Debug日志:logging.level.org.springframework.orm.jpa=DEBUG

開啟日志后再比較下在UserService中this調用、Controller中通過注入的UserService Bean調用createUserPublic的區別。

很明顯,this調用因沒走代理,事務沒有在createUserPublic生效,只在Repository的save生效:

// 在UserService中通過this調用public的createUserPublic[23:04:30.748] [http-nio-45678-exec-5] [DEBUG] [o.s.orm.jpa.JpaTransactionManager:370 ] - Creating new transaction with name [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT[DEBUG] [o.s.orm.jpa.JpaTransactionManager :370 ] - Creating new transaction with name [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT//在Controller中通過注入的UserService Bean調用createUserPublic[10:10:47.750] [http-nio-45678-exec-6] [DEBUG] [o.s.orm.jpa.JpaTransactionManager :370 ] - Creating new transaction with name [org.geekbang.time.commonmistakes.transaction.demo1.UserService.createUserPublic]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT

這種實現在Controller里處理異常顯得繁瑣,還不如直接把createUserWrong2加@Transactional注解,然后在Controller中直接調用該方法。這既能從外部(Controller中)調用UserService方法,方法又是public的能夠被動態代理AOP增強。

小結

務必確認調用被@Transactional注解標記的方法被public修飾,并且是通過Spring注入的Bean進行調用。

但有時因沒有正確處理異常,導致事務即便生效也不一定能回滾。

2 事務生效不代表能正確回滾

AOP實現事務:使用try/catch包裹@Transactional注解的方法:

當方法出現異常并滿足一定條件,在catch里可設置事務回滾 沒有異常則直接提交事務 一定條件

只有異常傳播出了被@Transactional注解的方法,事務才能回滾。

Spring的 TransactionAspectSupport#invokeWithinTransaction 就是在處理事務。觀察源碼得知,只有捕獲到異常后才能進行后續事務處理:

關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

默認情況下,出現RuntimeException(非受檢異常)或Error,Spring才會回滾事務。

Spring的DefaultTransactionAttribute:

受檢異常一般是業務異常或類似另一種方法的返回值,出現這種異常可能業務還能完成,所以不會主動回滾 而Error或RuntimeException代表非預期結果,應該回滾

關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

事務無法正常回滾的各種慘案 異常無法傳播出方法

關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

受檢異常

注冊的同時會有一次文件讀,若讀文件失敗,希望用戶注冊的DB操作回滾。因讀文件拋的是受檢異常,createUserError2傳播出去的也是受檢異常

關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

以上方法雖然避開了事務不生效的坑,但因異常處理不當,導致異常時依舊不回滾事務。

修復回滾失敗bug 1 手動設置讓當前事務處回滾態

若希望自己捕獲異常并處理,可手動設置讓當前事務處回滾態

關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

查看日志,事務確定回滾。

Transactional code has requested rollback:手動請求回滾。關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

2 注解中聲明,期望所有Exception都回滾事務 突破默認不回滾受檢異常的限制

關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

查看日志,提示回滾:

關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

該案例有DB操作、IO操作,在IO操作問題時期望DB事務也回滾,以確保邏輯一致性。 小結

由于異常處理不正確,導致雖然事務生效,但出現異常時沒回滾。Spring默認只對被@Transactional注解的方法出現RuntimeException和Error時回滾,所以若方法捕獲了異常,就需要通過手寫代碼處理事務回滾。若希望Spring針對其他異常也可回滾,可相應配置@Transactional注解的rollbackFor和noRollbackFor屬性覆蓋Spring的默認配置。

有些業務可能包含多次DB操作,不一定希望將兩次操作作為一個事務,這時就需仔細考慮事務傳播的配置。

3 事務傳播配置是否符合業務邏輯

案例

用戶注冊:會插入一個主用戶到用戶表,還會注冊一個關聯的子用戶。期望將子用戶注冊的DB操作作為一個獨立事務,即使失敗也不影響注冊主用戶的流程。

UserService:創建主、子用戶

關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

SubUserService:使子用戶注冊失敗。期望子用戶注冊作為一個事務單獨回滾而不影響注冊主用戶

關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

啟動調用后查看日志:事務回滾了

關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

不對呀!因為運行時異常逃出被@Transactional注解的createUserWrong,Spring當然會回滾事務。若期望主方法不回滾,應捕獲子方法所拋的異常。

修正方案

把subUserService#createSubUserWithExceptionError包上catch,這樣外層主方法createUserError2就不會出現異常

關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

啟動后查看日志注意到:

對createUserError2開啟異常處理 子方法因出現運行時異常,標記當前事務為回滾 主方法捕獲異常并打印create sub user error 主方法提交事務

但Controller出現一個UnexpectedRollbackException,異常描述提示最終該事務回滾了且為靜默回滾:因createUserError2本身并無異常,只不過提交后發現子方法已把當前事務設為回滾,無法完成提交。

明明無異常發生,但事務也不一定可提交因為主方法注冊主用戶的邏輯和子方法注冊子用戶的邏輯為同一事務,子邏輯標記了事務需回滾,主邏輯自然也無法提交。那么修復方式就明確了,獨立子邏輯的事務,即修正SubUserService注冊子用戶方法,為注解添加propagation = Propagation.REQUIRES_NEW設置REQUIRES_NEW事務傳播策略。即執行到該方法時開啟新事務,并掛起當前事務。創建一個新事務,若存在則暫停當前事務。類似同名的EJB事務屬性。注:實際事務暫停不會對所有事務管理器外的開箱。 這特別適于org.springframework.transaction.jta.JtaTransactionManager ,這就需要javax.transaction.TransactionManager被提供給它(這是服務器特定的標準Java EE)

關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

主方法無變化,依舊需捕獲異常,防止異常外泄導致主事務回滾,重命名為createUserRight:

關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

修正后再查看日志

Creating new transaction with name createUserRight

對createUserRight開啟主方法事務createMainUser finish創建主用戶完成Suspending current transaction, creating new transaction with name createSubUserWithExceptionRight主事務掛起,開啟新事務,即對createSubUserWithExceptionRight創建子用戶的邏輯Initiating transaction rollback子方法事務回滾Resuming suspended transaction after completion of inner transaction子方法事務完成,繼續主方法之前掛起的事務create sub user error:invalid status主方法捕獲到了子方法的異常Committing JPA transaction on EntityManager主方法的事務提交了,隨后我們在Controller里沒看到靜默回滾異常

小結

若方法涉及多次DB操作,并希望將它們作為獨立事務進行提交或回滾,即需考慮細化配置事務傳播方式,即配置@Transactional注解的Propagation屬性。

4 總結

若要針對private方法啟用事務,動態代理方式的AOP不可行,需要使用靜態織入方式的AOP,也就是在編譯期間織入事務增強代碼,可以配置Spring框架使用AspectJ來實現AOP。

以上就是關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)的詳細內容,更多關于Spring @Transaction數據庫回滾的資料請關注好吧啦網其它相關文章!

標簽: Spring
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
国产精品婷婷| 美女尤物久久精品| 国产美女视频一区二区| 亚洲va久久| 日韩精品欧美大片| 日韩国产欧美视频| 国产调教精品| 久久精品国产精品亚洲毛片| 美女视频黄免费的久久| 精品国产亚洲日本| 国产欧美成人| 另类综合日韩欧美亚洲| 精品国产黄a∨片高清在线| 麻豆成人综合网| 日韩av自拍| 福利一区二区| 久久一级电影| 亚洲欧美成人综合| 亚洲男人在线| 久久a爱视频| 日韩一区二区三区在线免费观看| 香蕉久久精品| 亚洲天堂免费| 国产精品欧美大片| 日韩欧美在线中字| 91久久国产| 日韩在线网址| 久久久久亚洲精品中文字幕| 亚洲天堂av影院| 夜夜嗨av一区二区三区网站四季av| 亚洲伊人精品酒店| 久久中文在线| 国户精品久久久久久久久久久不卡| 亚洲一区二区网站| 91精品国产自产精品男人的天堂| 久久不见久久见中文字幕免费 | 国产欧美一级| 国产精品成久久久久| 久久中文字幕av| 蜜臀va亚洲va欧美va天堂| 国产精品天堂蜜av在线播放| www.com.cn成人| 日韩中文字幕亚洲一区二区va在线 | 欧美jjzz| 91成人小视频| 88xx成人免费观看视频库| 午夜在线视频观看日韩17c| 国产欧美一区二区三区国产幕精品| 亚洲精品永久免费视频| 中文不卡在线| 国产精品蜜芽在线观看| 精品一区在线| 国产精品久久久久久久久久久久久久久 | 中文精品视频| 免费在线亚洲欧美| 91精品亚洲| 日韩不卡免费视频| 日韩精品久久久久久久电影99爱 | 亚洲一区成人| 精品丝袜久久| 一区二区91| 久久久一本精品| 911精品国产| 午夜日本精品| 精品国产免费人成网站| 亚洲精品看片| 91精品精品| 麻豆精品在线播放| 免费日韩一区二区| 国产成人精品福利| 日韩高清电影免费| 99成人在线| 91中文字幕精品永久在线| 日韩**一区毛片| 免费视频亚洲| 福利片在线一区二区| 亚洲精品一级二级三级| 香蕉久久精品| 久久精品国产精品亚洲毛片| 亚洲乱亚洲高清| 久久精品国产99久久| 精品美女视频| 日韩av黄色在线| 亚洲精品中文字幕乱码| 国产在线观看www| 国产日韩一区二区三免费高清 | 国产精品女主播一区二区三区| 国产一区二区三区天码| 日韩高清国产一区在线| 国产精品人人爽人人做我的可爱| 色黄视频在线观看| 欧美激情麻豆| 日本欧美一区二区| 亚洲一区二区三区四区五区午夜 | 99pao成人国产永久免费视频 | 日欧美一区二区| 性色一区二区| 亚洲激情黄色| 亚洲五月婷婷| 亚洲爱爱视频| 国产一区二区三区免费在线| 久久国产精品色av免费看| 中文字幕中文字幕精品| 亚洲欧美不卡| 国产精品普通话对白| 九九久久婷婷| 色婷婷久久久| 日韩精品诱惑一区?区三区| 丁香婷婷久久| 国产成人精选| 四虎成人av| 国产精品福利在线观看播放| 久久精品九色| 久久精品欧洲| 国产一区二区三区网| 国产伊人久久| 国产999精品在线观看| 国产精品大片| 麻豆精品视频在线| 麻豆91小视频| 国产精品国产三级国产在线观看| 麻豆精品新av中文字幕| 久久这里只有| 在线看片福利| 日韩中文视频| 欧美日中文字幕| 99re国产精品| 亚洲精品伦理| 欧美日韩夜夜| 欧美精品aa| 精品国产a一区二区三区v免费| 久久久91麻豆精品国产一区| 国产精品第一| 国产成人精品一区二区三区视频 | 综合亚洲色图| 日韩av中文字幕一区二区三区| 日韩欧美中文在线观看| 欧美欧美黄在线二区| 国产精品网在线观看| 精品国产aⅴ| 久久天堂av| 国产精品嫩草99av在线| 亚洲区第一页| 91亚洲精品视频在线观看| 国产精品视频一区二区三区综合| 美女在线视频一区| 日韩不卡免费高清视频| 99视频在线精品国自产拍免费观看| 999久久久国产精品| 日韩一级网站| 欧美精品影院| 欧美激情国产在线| 五月天激情综合网| 亚洲精品高潮| 免费看久久久| 亚洲午夜av| 亚洲啊v在线免费视频| 久久免费视频66| 欧美成人日韩| 日韩动漫一区| 在线看片国产福利你懂的| 国产毛片一区| 麻豆久久久久久| 久久精品亚洲欧美日韩精品中文字幕| 夜夜嗨一区二区| 国产欧美日韩综合一区在线播放| 卡一精品卡二卡三网站乱码| 1024精品一区二区三区| 日本在线成人| 高清一区二区| 羞羞答答国产精品www一本| 91亚洲精品在看在线观看高清| 97精品97| 天堂成人国产精品一区| 欧美国产亚洲精品| 免费av一区二区三区四区| 日韩精品导航| 国产999精品在线观看| 美女网站一区| 国产欧美大片| 好看的亚洲午夜视频在线| 青青草91久久久久久久久| 国产伦久视频在线观看| 亚洲精品麻豆| 久久久成人网| 欧美私人啪啪vps| 伊人久久大香线蕉av不卡| 91精品啪在线观看国产爱臀| 国产99久久久国产精品成人免费| 日本欧美久久久久免费播放网| 欧美日韩尤物久久| 欧美日本精品| 99视频精品| 精品国产亚洲一区二区三区| 免费日韩av片| 不卡福利视频| 日韩国产精品久久久久久亚洲| 国产一在线精品一区在线观看| 欧美亚洲一区二区三区| 欧美日韩四区|