欧美性猛交xxxx免费看_牛牛在线视频国产免费_天堂草原电视剧在线观看免费_国产粉嫩高清在线观看_国产欧美日本亚洲精品一5区

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

發(fā)現(xiàn)一個(gè)Spring事務(wù)的巨坑bug 你必須要小心了

jf_ro2CN3Fa ? 來(lái)源:蘇三說(shuō)技術(shù) ? 作者:蘇三說(shuō)技術(shù) ? 2022-10-11 18:17 ? 次閱讀

1.錯(cuò)誤的訪問(wèn)權(quán)限

2.方法被定義成final的

3.方法內(nèi)部調(diào)用

4.當(dāng)前實(shí)體沒(méi)有被spring管理

5.錯(cuò)誤的spring事務(wù)傳播特性

6.數(shù)據(jù)庫(kù)不支持事務(wù)

7.自己吞掉了異常

8.拋出的異常不正確

9.多線程調(diào)用

10.嵌套事務(wù)多回滾了

對(duì)于從事java開發(fā)工作的同學(xué)來(lái)說(shuō),spring的事務(wù)肯定再熟悉不過(guò)了。在某些業(yè)務(wù)場(chǎng)景下,如果同時(shí)有多張表的寫入操作,為了保證操作的原子性(要么同時(shí)成功,要么同時(shí)失?。┍苊鈹?shù)據(jù)不一致的情況,我們一般都會(huì)使用spring事務(wù)。

沒(méi)錯(cuò),spring事務(wù)大多數(shù)情況下,可以滿足我們的業(yè)務(wù)需求。但是今天我要告訴大家的是,它有很多坑,稍不注意事務(wù)就會(huì)失效。

不信,我們一起看看。

1.錯(cuò)誤的訪問(wèn)權(quán)限

@Service
publicclassUserService{

@Autowired
privateUserMapperuserMapper;

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

我們可以看到add方法的訪問(wèn)權(quán)限被定義成了private,這樣會(huì)導(dǎo)致事務(wù)失效,spring要求被代理方法必須是public的。

AbstractFallbackTransactionAttributeSource類的computeTransactionAttribute方法中有個(gè)判斷,如果目標(biāo)方法不是public,則TransactionAttribute返回null,即不支持事務(wù)。

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的,這樣會(huì)導(dǎo)致spring aop生成的代理對(duì)象不能復(fù)寫該方法,而讓事務(wù)失效。

3.方法內(nèi)部調(diào)用

@Service
publicclassUserService{

@Autowired
privateUserMapperuserMapper;

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

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

我們看到在事務(wù)方法add中,直接調(diào)用事務(wù)方法updateStatus。從前面介紹的內(nèi)容可以知道,updateStatus方法擁有事務(wù)的能力是因?yàn)閟pring aop生成代理了對(duì)象,但是這種方法直接調(diào)用了this對(duì)象的方法,所以u(píng)pdateStatus方法不會(huì)生成事務(wù)。

4.當(dāng)前實(shí)體沒(méi)有被spring管理

//@Service
publicclassUserService{

@Autowired
privateUserMapperuserMapper;

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

我們可以看到UserService類沒(méi)有定義@Service注解,即沒(méi)有交給spring管理bean實(shí)例,所以它的add方法也不會(huì)生成事務(wù)。

5.錯(cuò)誤的spring事務(wù)傳播特性

@Service
publicclassUserService{

@Autowired
privateUserMapperuserMapper;

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

}

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

6.數(shù)據(jù)庫(kù)不支持事務(wù)

msql8以前的版本數(shù)據(jù)庫(kù)引擎是支持myslam和innerdb的。我以前也用過(guò),對(duì)應(yīng)查多寫少的單表操作,可能會(huì)把表的數(shù)據(jù)庫(kù)引擎定義成myslam,這樣可以提升查詢效率。但是,要千萬(wàn)記得一件事情,myslam只支持表鎖,并且不支持事務(wù)。所以,對(duì)這類表的寫入操作事務(wù)會(huì)失效。

7.自己吞掉了異常

@Slf4j
@Service
publicclassUserService{

@Autowired
privateUserMapperuserMapper;

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

這種情況下事務(wù)不會(huì)回滾,因?yàn)?a target="_blank">開發(fā)者自己捕獲了異常,又沒(méi)有拋出。事務(wù)的AOP無(wú)法捕獲異常,導(dǎo)致即使出現(xiàn)了異常,事務(wù)也不會(huì)回滾。

8.拋出的異常不正確

@Slf4j
@Service
publicclassUserService{

@Autowired
privateUserMapperuserMapper;

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

}

這種情況下,開發(fā)人員自己捕獲了異常,又拋出了異常:Exception,事務(wù)也不會(huì)回滾。因?yàn)閟pring事務(wù),默認(rèn)情況下只會(huì)回滾RuntimeException(運(yùn)行時(shí)異常)和Error(錯(cuò)誤),不會(huì)回滾Exception。

9.多線程調(diào)用

@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表數(shù)據(jù)");
}
}

我們可以看到事務(wù)方法add中,調(diào)用了事務(wù)方法doOtherThing,但是事務(wù)方法doOtherThing是在另外一個(gè)線程中調(diào)用的,這樣會(huì)導(dǎo)致兩個(gè)事務(wù)方法不在同一個(gè)線程中,獲取到的數(shù)據(jù)庫(kù)連接不一樣,從而是兩個(gè)不同的事務(wù)。如果想doOtherThing方法中拋了異常,add方法也回滾是不可能的。

如果看過(guò)spring事務(wù)源碼的朋友,可能會(huì)知道spring的事務(wù)是通過(guò)數(shù)據(jù)庫(kù)連接來(lái)實(shí)現(xiàn)的。當(dāng)前線程中保存了一個(gè)map,key是數(shù)據(jù)源,value是數(shù)據(jù)庫(kù)連接。

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

我們說(shuō)的同一個(gè)事務(wù),其實(shí)是指同一個(gè)數(shù)據(jù)庫(kù)連接,只有擁有同一個(gè)數(shù)據(jù)庫(kù)連接才能同時(shí)提交和回滾。如果在不同的線程,拿到的數(shù)據(jù)庫(kù)連接肯定是不一樣的,所以是不同的事務(wù)。

10.嵌套事務(wù)多回滾了

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表數(shù)據(jù)");
}
}

這種情況使用了嵌套的內(nèi)部事務(wù),原本是希望調(diào)用roleService.doOtherThing方法時(shí),如果出現(xiàn)了異常,只回滾doOtherThing方法里的內(nèi)容,不回滾 userMapper.insertUser里的內(nèi)容,即回滾保存點(diǎn)。。但事實(shí)是,insertUser也回滾了。

why?

因?yàn)閐oOtherThing方法出現(xiàn)了異常,沒(méi)有手動(dòng)捕獲,會(huì)繼續(xù)往上拋,到外層add方法的代理方法中捕獲了異常。所以,這種情況是直接回滾了整個(gè)事務(wù),不只回滾單個(gè)保存點(diǎn)。

怎么樣才能只回滾保存點(diǎn)呢?

@Slf4j
@Service
publicclassUserService{

@Autowired
privateUserMapperuserMapper;

@Autowired
privateRoleServiceroleService;

@Transactional
publicvoidadd(UserModeluserModel)throwsException{

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

}

在代碼中手動(dòng)把內(nèi)部嵌套事務(wù)放在try/catch中,并且不繼續(xù)往拋異常。

介紹到這里,你會(huì)發(fā)現(xiàn)spring事務(wù)的坑還是挺多的~

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • JAVA
    +關(guān)注

    關(guān)注

    19

    文章

    2975

    瀏覽量

    105187
  • 數(shù)據(jù)庫(kù)
    +關(guān)注

    關(guān)注

    7

    文章

    3851

    瀏覽量

    64711
  • spring
    +關(guān)注

    關(guān)注

    0

    文章

    340

    瀏覽量

    14394

原文標(biāo)題:發(fā)現(xiàn)一個(gè)Spring事務(wù)的巨坑bug,可是官方都不承認(rèn)?大家來(lái)評(píng)評(píng)理!

文章出處:【微信號(hào):芋道源碼,微信公眾號(hào):芋道源碼】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    Spring事務(wù)失效的十種常見(jiàn)場(chǎng)景

    Spring針對(duì)Java Transaction API (JTA)、JDBC、Hibernate和Java Persistence API(JPA)等事務(wù) API,實(shí)現(xiàn)致的編程模
    的頭像 發(fā)表于 12-11 15:03 ?960次閱讀

    Spring事務(wù)實(shí)現(xiàn)原理

    作者:京東零售 范錫軍 1、引言 springspring-tx模塊提供對(duì)事務(wù)管理支持,使用spring
    的頭像 發(fā)表于 11-08 10:10 ?878次閱讀
    <b class='flag-5'>Spring</b><b class='flag-5'>事務(wù)</b>實(shí)現(xiàn)原理

    什么是java spring

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

    Spring事務(wù)分析的實(shí)現(xiàn)方式

    Spring事務(wù)原理分析
    發(fā)表于 07-02 15:19

    詳解Spring事務(wù)管理

    在學(xué)習(xí)spring事務(wù)管理時(shí),我忍不住要問(wèn),spring為什么進(jìn)行事務(wù)管理,spring怎么進(jìn)行的事務(wù)
    發(fā)表于 07-12 06:54

    Spring事務(wù)管理詳解說(shuō)明

    Spring事務(wù)管理詳解
    發(fā)表于 05-20 13:46

    發(fā)現(xiàn)Tardis的PDA的個(gè)BUG怎么解決?

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

    啟動(dòng)Spring Boot項(xiàng)目應(yīng)用的三種方法

    基礎(chǔ)。我們知道Spring Boot是個(gè)什么,那么我們又該如何啟動(dòng)Spring Boot應(yīng)用呢?這里小編給大家推薦常用的三種方法。分別是
    發(fā)表于 01-14 17:33

    蘋果iOS 10.2默默修復(fù)個(gè)未被發(fā)現(xiàn)的神級(jí)BUG,知道?

     如果升級(jí)iOS 10.2,那么iPhone上那個(gè)神級(jí)Bug,終于被蘋果發(fā)現(xiàn)并修復(fù),雖然蘋果沒(méi)有提及,但還有開發(fā)者發(fā)現(xiàn),蘋果在iOS 10.2中修復(fù)兩
    發(fā)表于 12-22 10:02 ?929次閱讀

    spring中聲明式事務(wù)實(shí)現(xiàn)原理猜想

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

    淺談Spring事務(wù)的那些

    對(duì)于從事java開發(fā)工作的同學(xué)來(lái)說(shuō),spring事務(wù)肯定再熟悉不過(guò)了。在某些業(yè)務(wù)場(chǎng)景下,如果同時(shí)有多張表的寫入操作,為了保證操作的原子性(要么同時(shí)成功,要么同時(shí)失敗)避免數(shù)據(jù)不致的情況,我們
    的頭像 發(fā)表于 10-11 10:31 ?779次閱讀

    淺談Spring事務(wù)底層原理

    開啟Spring事務(wù)本質(zhì)上就是增加了個(gè)Advisor,但我們使用@EnableTransactionManagement注解來(lái)開啟Spring
    的頭像 發(fā)表于 12-06 09:56 ?737次閱讀

    8個(gè)Spring事務(wù)失效的場(chǎng)景介紹

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

    spring事務(wù)失效的些場(chǎng)景

    致的情況,我們般都會(huì)用到spring事務(wù)。 確實(shí),spring事務(wù)用起來(lái)賊爽,就用
    的頭像 發(fā)表于 10-08 14:27 ?487次閱讀
    <b class='flag-5'>spring</b><b class='flag-5'>事務(wù)</b>失效的<b class='flag-5'>一</b>些場(chǎng)景

    Spring事務(wù)傳播性的相關(guān)知識(shí)

    本文主要介紹Spring事務(wù)傳播性的相關(guān)知識(shí)。
    的頭像 發(fā)表于 01-10 09:29 ?497次閱讀
    <b class='flag-5'>Spring</b><b class='flag-5'>事務(wù)</b>傳播性的相關(guān)知識(shí)