在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

發現一個Spring事務的巨坑bug 你必須要小心了

jf_ro2CN3Fa ? 來源:蘇三說技術 ? 作者:蘇三說技術 ? 2022-10-11 18:17 ? 次閱讀

1.錯誤的訪問權限

2.方法被定義成final的

3.方法內部調用

4.當前實體沒有被spring管理

5.錯誤的spring事務傳播特性

6.數據庫不支持事務

7.自己吞掉了異常

8.拋出的異常不正確

9.多線程調用

10.嵌套事務多回滾了

對于從事java開發工作的同學來說,spring的事務肯定再熟悉不過了。在某些業務場景下,如果同時有多張表的寫入操作,為了保證操作的原子性(要么同時成功,要么同時失敗)避免數據不一致的情況,我們一般都會使用spring事務。

沒錯,spring事務大多數情況下,可以滿足我們的業務需求。但是今天我要告訴大家的是,它有很多坑,稍不注意事務就會失效。

不信,我們一起看看。

1.錯誤的訪問權限

@Service
publicclassUserService{

@Autowired
privateUserMapperuserMapper;

@Transactional
privatevoidadd(UserModeluserModel){
userMapper.insertUser(userModel);
}
}

我們可以看到add方法的訪問權限被定義成了private,這樣會導致事務失效,spring要求被代理方法必須是public的。

AbstractFallbackTransactionAttributeSource類的computeTransactionAttribute方法中有個判斷,如果目標方法不是public,則TransactionAttribute返回null,即不支持事務。

protectedTransactionAttributecomputeTransactionAttribute(Methodmethod,@NullableClasstargetClass){
//Don'tallowno-publicmethodsasrequired.
if(allowPublicMethodsOnly()&&!Modifier.isPublic(method.getModifiers())){
returnnull;
}

//Themethodmaybeonaninterface,butweneedattributesfromthetargetclass.
//Ifthetargetclassisnull,themethodwillbeunchanged.
MethodspecificMethod=AopUtils.getMostSpecificMethod(method,targetClass);

//Firsttryisthemethodinthetargetclass.
TransactionAttributetxAttr=findTransactionAttribute(specificMethod);
if(txAttr!=null){
returntxAttr;
}

//Secondtryisthetransactionattributeonthetargetclass.
txAttr=findTransactionAttribute(specificMethod.getDeclaringClass());
if(txAttr!=null&&ClassUtils.isUserLevelMethod(method)){
returntxAttr;
}

if(specificMethod!=method){
//Fallbackistolookattheoriginalmethod.
txAttr=findTransactionAttribute(method);
if(txAttr!=null){
returntxAttr;
}
//Lastfallbackistheclassoftheoriginalmethod.
txAttr=findTransactionAttribute(method.getDeclaringClass());
if(txAttr!=null&&ClassUtils.isUserLevelMethod(method)){
returntxAttr;
}
}

returnnull;
}

2.方法被定義成final的

@Service
publicclassUserService{

@Autowired
privateUserMapperuserMapper;

@Transactional
publicfinalvoidadd(UserModeluserModel){
userMapper.insertUser(userModel);
}
}

我們可以看到add方法被定義成了final的,這樣會導致spring aop生成的代理對象不能復寫該方法,而讓事務失效。

3.方法內部調用

@Service
publicclassUserService{

@Autowired
privateUserMapperuserMapper;

@Transactional
publicvoidadd(UserModeluserModel){
userMapper.insertUser(userModel);
updateStatus(userModel);
}

@Transactional
publicvoidupdateStatus(UserModeluserModel){
//doSameThing();
}
}

我們看到在事務方法add中,直接調用事務方法updateStatus。從前面介紹的內容可以知道,updateStatus方法擁有事務的能力是因為spring aop生成代理了對象,但是這種方法直接調用了this對象的方法,所以updateStatus方法不會生成事務。

4.當前實體沒有被spring管理

//@Service
publicclassUserService{

@Autowired
privateUserMapperuserMapper;

@Transactional
publicvoidadd(UserModeluserModel){
userMapper.insertUser(userModel);
}
}

我們可以看到UserService類沒有定義@Service注解,即沒有交給spring管理bean實例,所以它的add方法也不會生成事務。

5.錯誤的spring事務傳播特性

@Service
publicclassUserService{

@Autowired
privateUserMapperuserMapper;

@Transactional(propagation=Propagation.NEVER)
publicvoidadd(UserModeluserModel){
userMapper.insertUser(userModel);
}

}

我們可以看到add方法的事務傳播特性定義成了Propagation.NEVER,這種類型的傳播特性不支持事務,如果有事務則會拋異常。只有這三種傳播特性才會創建新事務:PROPAGATION_REQUIRED,PROPAGATION_REQUIRES_NEW,PROPAGATION_NESTED。

6.數據庫不支持事務

msql8以前的版本數據庫引擎是支持myslam和innerdb的。我以前也用過,對應查多寫少的單表操作,可能會把表的數據庫引擎定義成myslam,這樣可以提升查詢效率。但是,要千萬記得一件事情,myslam只支持表鎖,并且不支持事務。所以,對這類表的寫入操作事務會失效。

7.自己吞掉了異常

@Slf4j
@Service
publicclassUserService{

@Autowired
privateUserMapperuserMapper;

@Transactional
publicvoidadd(UserModeluserModel){
try{
userMapper.insertUser(userModel);
}catch(Exceptione){
log.error(e.getMessage(),e);
}
}
}

這種情況下事務不會回滾,因為開發者自己捕獲了異常,又沒有拋出。事務的AOP無法捕獲異常,導致即使出現了異常,事務也不會回滾。

8.拋出的異常不正確

@Slf4j
@Service
publicclassUserService{

@Autowired
privateUserMapperuserMapper;

@Transactional
publicvoidadd(UserModeluserModel)throwsException{
try{
userMapper.insertUser(userModel);
}catch(Exceptione){
log.error(e.getMessage(),e);
thrownewException(e);
}
}

}

這種情況下,開發人員自己捕獲了異常,又拋出了異常:Exception,事務也不會回滾。因為spring事務,默認情況下只會回滾RuntimeException(運行時異常)和Error(錯誤),不會回滾Exception。

9.多線程調用

@Slf4j
@Service
publicclassUserService{

@Autowired
privateUserMapperuserMapper;
@Autowired
privateRoleServiceroleService;

@Transactional
publicvoidadd(UserModeluserModel)throwsException{
userMapper.insertUser(userModel);
newThread(()->{
roleService.doOtherThing();
}).start();
}
}

@Service
publicclassRoleService{

@Transactional
publicvoiddoOtherThing(){
System.out.println("保存role表數據");
}
}

我們可以看到事務方法add中,調用了事務方法doOtherThing,但是事務方法doOtherThing是在另外一個線程中調用的,這樣會導致兩個事務方法不在同一個線程中,獲取到的數據庫連接不一樣,從而是兩個不同的事務。如果想doOtherThing方法中拋了異常,add方法也回滾是不可能的。

如果看過spring事務源碼的朋友,可能會知道spring的事務是通過數據庫連接來實現的。當前線程中保存了一個map,key是數據源,value是數據庫連接。

privatestaticfinalThreadLocal>resources=
newNamedThreadLocal<>("Transactionalresources");

我們說的同一個事務,其實是指同一個數據庫連接,只有擁有同一個數據庫連接才能同時提交和回滾。如果在不同的線程,拿到的數據庫連接肯定是不一樣的,所以是不同的事務。

10.嵌套事務多回滾了

publicclassUserService{

@Autowired
privateUserMapperuserMapper;

@Autowired
privateRoleServiceroleService;

@Transactional
publicvoidadd(UserModeluserModel)throwsException{
userMapper.insertUser(userModel);
roleService.doOtherThing();
}
}

@Service
publicclassRoleService{

@Transactional(propagation=Propagation.NESTED)
publicvoiddoOtherThing(){
System.out.println("保存role表數據");
}
}

這種情況使用了嵌套的內部事務,原本是希望調用roleService.doOtherThing方法時,如果出現了異常,只回滾doOtherThing方法里的內容,不回滾 userMapper.insertUser里的內容,即回滾保存點。。但事實是,insertUser也回滾了。

why?

因為doOtherThing方法出現了異常,沒有手動捕獲,會繼續往上拋,到外層add方法的代理方法中捕獲了異常。所以,這種情況是直接回滾了整個事務,不只回滾單個保存點。

怎么樣才能只回滾保存點呢?

@Slf4j
@Service
publicclassUserService{

@Autowired
privateUserMapperuserMapper;

@Autowired
privateRoleServiceroleService;

@Transactional
publicvoidadd(UserModeluserModel)throwsException{

userMapper.insertUser(userModel);
try{
roleService.doOtherThing();
}catch(Exceptione){
log.error(e.getMessage(),e);
}
}

}

在代碼中手動把內部嵌套事務放在try/catch中,并且不繼續往拋異常。

介紹到這里,你會發現spring事務的坑還是挺多的~

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • JAVA
    +關注

    關注

    19

    文章

    2967

    瀏覽量

    104749
  • 數據庫
    +關注

    關注

    7

    文章

    3799

    瀏覽量

    64388
  • spring
    +關注

    關注

    0

    文章

    340

    瀏覽量

    14343

原文標題:發現一個Spring事務的巨坑bug,可是官方都不承認?大家來評評理!

文章出處:【微信號:芋道源碼,微信公眾號:芋道源碼】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    Spring事務失效的十種常見場景

    Spring針對Java Transaction API (JTA)、JDBC、Hibernate和Java Persistence API(JPA)等事務 API,實現致的編程模
    的頭像 發表于 12-11 15:03 ?915次閱讀

    Spring事務實現原理

    作者:京東零售 范錫軍 1、引言 springspring-tx模塊提供事務管理支持,使用spring
    的頭像 發表于 11-08 10:10 ?824次閱讀
    <b class='flag-5'>Spring</b><b class='flag-5'>事務</b>實現原理

    什么是java spring

    ,應用對象被聲明式地組合,典型地是在XML文件里。Spring也提供很多基礎功能(事務管理、持久化框架集成等等),將應用邏輯的開發留給
    發表于 09-11 11:16

    Spring事務分析的實現方式

    Spring事務原理分析
    發表于 07-02 15:19

    詳解Spring事務管理

    在學習spring事務管理時,我忍不住要問,spring為什么進行事務管理,spring怎么進行的事務
    發表于 07-12 06:54

    Spring事務管理詳解說明

    Spring事務管理詳解
    發表于 05-20 13:46

    發現Tardis的PDA的BUG怎么解決?

    今天我懷著激動的心情把Tardis的PDA的程序(5.17最新版)燒進了板子,的確被鎮住了,華麗的界面,牛叉的設計,只能用六體投地來形容只不過我點開文本瀏覽器時,第次是讓找文本文件,然后我選
    發表于 08-19 04:23

    啟動Spring Boot項目應用的三種方法

    基礎。我們知道Spring Boot是什么,那么我們又該如何啟動Spring Boot應用呢?這里小編給大家推薦常用的三種方法。分別是
    發表于 01-14 17:33

    蘋果iOS 10.2默默修復未被發現的神級BUG知道?

     如果升級iOS 10.2,那么iPhone上那個神級Bug,終于被蘋果發現并修復,雖然蘋果沒有提及,但還有開發者發現,蘋果在iOS 10.2中修復兩
    發表于 12-22 10:02 ?924次閱讀

    spring中聲明式事務實現原理猜想

    ? @Transactional注解簡介 @Transactional 是spring中聲明式事務管理的注解配置方式,相信這個注解的作用大家都很清楚。 @Transactional 注解可以幫助
    的頭像 發表于 10-13 09:20 ?1630次閱讀

    淺談Spring事務的那些

    對于從事java開發工作的同學來說,spring事務肯定再熟悉不過了。在某些業務場景下,如果同時有多張表的寫入操作,為了保證操作的原子性(要么同時成功,要么同時失敗)避免數據不致的情況,我們
    的頭像 發表于 10-11 10:31 ?751次閱讀

    淺談Spring事務底層原理

    開啟Spring事務本質上就是增加了Advisor,但我們使用@EnableTransactionManagement注解來開啟Spring
    的頭像 發表于 12-06 09:56 ?695次閱讀

    8Spring事務失效的場景介紹

    作為Java開發工程師,相信大家對Spring事務的使用并不陌生。但是可能只是停留在基礎的使用層面上,在遇到些比較特殊的場景,事務可能
    的頭像 發表于 05-11 10:41 ?675次閱讀
    8<b class='flag-5'>個</b><b class='flag-5'>Spring</b><b class='flag-5'>事務</b>失效的場景介紹

    spring事務失效的些場景

    致的情況,我們般都會用到spring事務。 確實,spring事務用起來賊爽,就用
    的頭像 發表于 10-08 14:27 ?447次閱讀
    <b class='flag-5'>spring</b><b class='flag-5'>事務</b>失效的<b class='flag-5'>一</b>些場景

    Spring事務傳播性的相關知識

    本文主要介紹Spring事務傳播性的相關知識。
    的頭像 發表于 01-10 09:29 ?447次閱讀
    <b class='flag-5'>Spring</b><b class='flag-5'>事務</b>傳播性的相關知識
    主站蜘蛛池模板: 五月深爱婷婷| 久久理论片| 一级片在线免费看| 天天拍夜夜添久久精品中文| 美女被免费视频的网站| 欧美国产精品主播一区| 性爽爽| 午夜dy888理论在线播放| 正在播放淫亚洲| 色久月| 狠狠色狠狠色综合日日小蛇| 6080伦理久久亚洲精品| 黄色视网站| 视频一区二区三区在线观看| 亚洲bt天堂| 成年午夜一级毛片视频| 欧美另类69xxxxxhd| 中文字幕va一区二区三区| 亚洲高清免费在线观看| 六月天婷婷| 天天色天| 亚洲第一在线| 国产不卡毛片| 好紧好爽太大了h快穿| 日韩欧免费一区二区三区| 国产成人优优影院| 黄色网址免费在线| 天天看天天摸天天操| 国产偷窥女洗浴在线观看亚洲| 喷潮白浆| 亚洲成综合人影院在院播放| www.激情五月.com| 视频在线免费观看| 天天色综合色| 天天爽夜夜爽夜夜爽| 亚洲黄色第一页| 欧美一级黄色影片| 天天摸天天看天天做天天爽| 高清视频一区二区| 久久艹综合| 国产免费福利网站|