chinese直男口爆体育生外卖, 99久久er热在这里只有精品99, 又色又爽又黄18禁美女裸身无遮挡, gogogo高清免费观看日本电视,私密按摩师高清版在线,人妻视频毛茸茸,91论坛 兴趣闲谈,欧美 亚洲 精品 8区,国产精品久久久久精品免费

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

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

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

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

jf_ro2CN3Fa ? 來源:稀土掘金技術(shù)社區(qū) ? 2023-12-11 15:03 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

1 概述

Spring針對(duì)Java Transaction API (JTA)、JDBC、Hibernate和Java Persistence API(JPA)等事務(wù) API,實(shí)現(xiàn)了一致的編程模型,而Spring的聲明式事務(wù)功能更是提供了極其方便的事務(wù)配置方式,配合Spring Boot的自動(dòng)配置,大多數(shù)Spring Boot項(xiàng)目只需要在方法上標(biāo)記@Transactional注解,即可一鍵開啟方法的事務(wù)性配置。

但是,事務(wù)如果沒有被正確出,很有可能會(huì)導(dǎo)致事務(wù)的失效,帶來意想不到的數(shù)據(jù)不一致問題,隨后就是大量的人工接入查看和修復(fù)數(shù)據(jù),該篇主要分享Spring事務(wù)在技術(shù)上的正確使用方式,避免因?yàn)槭聞?wù)處理不當(dāng)導(dǎo)致業(yè)務(wù)邏輯產(chǎn)生大量偶發(fā)性BUG。

在分析事務(wù)失效的常見場(chǎng)景之前,我們先來了解一下:事務(wù)的傳播類型@Transactionnal 注解的不同屬性的含義。

事務(wù)的傳播類型

//如果有事務(wù),那么加入事務(wù),沒有的話新建一個(gè)(默認(rèn))
@Transactional(propagation=Propagation.REQUIRED)
//容器不為這個(gè)方法開啟事務(wù)
@Transactional(propagation=Propagation.NOT_SUPPORTED)
//不管是否存在事務(wù),都創(chuàng)建一個(gè)新的事務(wù),原來的掛起,新的執(zhí)行完畢,繼續(xù)執(zhí)行老的事務(wù)
@Transactional(propagation=Propagation.REQUIRES_NEW)
//必須在一個(gè)已有的事務(wù)中執(zhí)行,否則拋出異常
@Transactional(propagation=Propagation.MANDATORY)
//必須在一個(gè)沒有的事務(wù)中執(zhí)行,否則拋出異常(與Propagation.MANDATORY相反)
@Transactional(propagation=Propagation.NEVER)
//如果其他bean調(diào)用這個(gè)方法,在其他bean中聲明事務(wù),那就用事務(wù),如果其他bean沒有聲明事務(wù),那就不用事務(wù)
@Transactional(propagation=Propagation.SUPPORTS)

isolation

該屬性用于設(shè)置底層數(shù)據(jù)庫(kù)的事務(wù)隔離級(jí)別,事務(wù)的隔離級(jí)別介紹:

//讀取未提交數(shù)據(jù)(會(huì)出現(xiàn)臟讀,不可重復(fù)讀)基本不使用
@Transactional(isolation=Isolation.READ_UNCOMMITTED)
//讀取已提交數(shù)據(jù)(會(huì)出現(xiàn)不可重復(fù)讀和幻讀)Oracle默認(rèn)
@Transactional(isolation=Isolation.READ_COMMITTED)
//可重復(fù)讀(會(huì)出現(xiàn)幻讀)MySQL默認(rèn)
@Transactional(isolation=Isolation.REPEATABLE_READ)
//串行化
@Transactional(isolation=Isolation.SERIALIZABLE)

@Transactionnal注解屬性

@Transactional注解可以作用于接口、接口方法、類以及類方法上,它可以通過不同的參數(shù)來選擇什么類型Exception異常下執(zhí)行回滾或者不回滾操作。

d4855e8a-9640-11ee-8b88-92fbcf53809c.png

1. 事務(wù)方法未被Spring管理

如果事務(wù)方法所在的類沒有注冊(cè)到Spring IOC容器中,也就是說,事務(wù)方法所在類并沒有被Spring管理,則Spring事務(wù)會(huì)失效,舉個(gè)例子:

publicclassProductServiceImplextendsServiceImplimplementsIProductService{

@Autowired
privateProductMapperproductMapper;

@Override
@Transactional(propagation=Propagation.REQUIRES_NEW)
publicvoidupdateProductStockById(IntegerstockCount,LongproductId){
productMapper.updateProductStockById(stockCount,productId);
}
}

ProductServiceImpl實(shí)現(xiàn)類上沒有添加@Service注解,Product的實(shí)例也就沒有被加載到Spring IOC容器,此時(shí)updateProductStockById()方法的事務(wù)就會(huì)在Spring中失效。

2. 方法使用final類型修飾

有時(shí)候,某個(gè)方法不想被子類重新,這時(shí)可以將該方法定義成final的。普通方法這樣定義是沒問題的,但如果將事務(wù)方法定義成final,例如:

@Service
publicclassOrderServiceImpl{

@Transactional
publicfinalvoidcancel(OrderDTOorderDTO){
//取消訂單
cancelOrder(orderDTO);
}
}

OrderServiceImpl的cancel取消訂單方法被final修飾符修飾,Spring事務(wù)底層使用了AOP,也就是通過JDK動(dòng)態(tài)代理或者cglib,幫我們生成了代理類,在代理類中實(shí)現(xiàn)的事務(wù)功能。但如果某個(gè)方法用final修飾了,那么在它的代理類中,就無法重寫該方法,從而無法添加事務(wù)功能。這種情況事務(wù)就會(huì)在Spring中失效。

Tips: 如果某個(gè)方法是static的,同樣無法通過動(dòng)態(tài)代理將方法聲明為事務(wù)方法。

3. 非public修飾的方法

如果事務(wù)方式不是public修飾,此時(shí)Spring事務(wù)會(huì)失效,舉個(gè)例子:

@Service
publicclassProductServiceImplextendsServiceImplimplementsIProductService{

@Autowired
privateProductMapperproductMapper;

@Override
@Transactional(propagation=Propagation.REQUIRES_NEW)
privatevoidupdateProductStockById(IntegerstockCount,StringproductId){
productMapper.updateProductStockById(stockCount,productId);
}
}

雖然ProductServiceImpl添加了@Service注解,同時(shí)updateProductStockById()方法上添加了@Transactional(propagation = Propagation.REQUIRES_NEW)注解,但是由于事務(wù)方法updateProductStockById()被 private 定義為方法內(nèi)私有,同樣Spring事務(wù)會(huì)失效。

4. 同一個(gè)類中的方法相互調(diào)用

@Service
publicclassOrderServiceImplextendsServiceImplimplementsIOrderService{
@Autowired
privateOrderMapperorderMapper;
@Autowired
privateProductMapperproductMapper;

@Override
publicResponseEntitysubmitOrder(Orderorder){
//保存生成訂單信息
longorderNo=Math.abs(ThreadLocalRandom.current().nextLong(1000));
order.setOrderNo("ORDER_"+orderNo);
orderMapper.insert(order);

//扣減庫(kù)存
this.updateProductStockById(order.getProductId(),1L);
returnnewResponseEntity(HttpStatus.OK);
}

@Transactional(propagation=Propagation.REQUIRES_NEW)
publicvoidupdateProductStockById(Integernum,LongproductId){
productMapper.updateProductStockById(num,productId);
}
}

submitOrder()方法和updateProductStockById()方法都在OrderService類中,然而submitOrder()方法沒有添加事務(wù)注解,updateProductStockById()方法雖然添加了事務(wù)注解,這種情況updateProductStockById()會(huì)在Spring事務(wù)中失效。

5. 方法的事務(wù)傳播類型不支持事務(wù)

如果內(nèi)部方法的事務(wù)傳播類型為不支持事務(wù)的傳播類型,則內(nèi)部方法的事務(wù)同樣會(huì)在Spring中失效,舉個(gè)例子:

@Service
publicclassOrderServiceImplextendsServiceImplimplementsIOrderService{
@Autowired
privateOrderMapperorderMapper;
@Autowired
privateProductMapperproductMapper;

@Override
@Transactional(propagation=Propagation.REQUIRES_NEW)
publicResponseEntitysubmitOrder(Orderorder){
longorderNo=Math.abs(ThreadLocalRandom.current().nextLong(1000));
order.setOrderNo("ORDER_"+orderNo);
orderMapper.insert(order);

//扣減庫(kù)存
this.updateProductStockById(order.getProductId(),1L);
returnnewResponseEntity(HttpStatus.OK);
}


/**
*扣減庫(kù)存方法事務(wù)類型聲明為NOT_SUPPORTED不支持事務(wù)的傳播
*/
@Transactional(propagation=Propagation.NOT_SUPPORTED)
publicvoidupdateProductStockById(Integernum,LongproductId){
productMapper.updateProductStockById(num,productId);
}
}

6. 異常被內(nèi)部catch,程序生吞異常

@Service
publicclassOrderServiceImplextendsServiceImplimplementsIOrderService{
@Autowired
privateOrderMapperorderMapper;
@Autowired
privateProductMapperproductMapper;

@Override
@Transactional(propagation=Propagation.REQUIRES_NEW)
publicResponseEntitysubmitOrder(Orderorder){
longorderNo=Math.abs(ThreadLocalRandom.current().nextLong(1000));
order.setOrderNo("ORDER_"+orderNo);
orderMapper.insert(order);

//扣減庫(kù)存
this.updateProductStockById(order.getProductId(),1L);
returnnewResponseEntity(HttpStatus.OK);
}

/**
*扣減庫(kù)存方法事務(wù)類型聲明為NOT_SUPPORTED不支持事務(wù)的傳播
*/
@Transactional(propagation=Propagation.NOT_SUPPORTED)
publicvoidupdateProductStockById(Integernum,LongproductId){
try{
productMapper.updateProductStockById(num,productId);
}catch(Exceptione){
//這里僅僅是捕獲異常之后的打?。ㄏ喈?dāng)于程序吞掉了異常)
log.error("ErrorupdatingproductStock:{}",e);
}
}
}

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

Spring事務(wù)生效的前提是連接的數(shù)據(jù)庫(kù)支持事務(wù),如果底層的數(shù)據(jù)庫(kù)都不支持事務(wù),則Spring事務(wù)肯定會(huì)失效的,例如:使用MySQL數(shù)據(jù)庫(kù),選用MyISAM存儲(chǔ)引擎,因?yàn)镸yISAM存儲(chǔ)引擎本身不支持事務(wù),因此事務(wù)毫無疑問會(huì)失效。

8. 未配置開啟事務(wù)

如果項(xiàng)目中沒有配置Spring的事務(wù)管理器,即使使用了Spring的事務(wù)管理功能,Spring的事務(wù)也不會(huì)生效,例如,如果你是Spring Boot項(xiàng)目,沒有在SpringBoot項(xiàng)目中配置如下代碼:

@Bean
publicPlatformTransactionManagertransactionManager(DataSourcedataSource){
returnnewDataSourceTransactionManager(dataSource);
}

如果是以往的Spring MVC項(xiàng)目,如果沒有配置下面的代碼,Spring事務(wù)也不會(huì)生效,正常需要在applicationContext.xml文件中,手動(dòng)配置事務(wù)相關(guān)參數(shù),比如:

 








 




9. 錯(cuò)誤的傳播特性

其實(shí),我們?cè)谑褂聾Transactional注解時(shí),是可以指定propagation參數(shù)的。

該參數(shù)的作用是指定事務(wù)的傳播特性,目前Spring支持7種傳播特性:

REQUIRED 如果當(dāng)前上下文中存在事務(wù),那么加入該事務(wù),如果不存在事務(wù),創(chuàng)建一個(gè)事務(wù),這是默認(rèn)的傳播屬性值。

SUPPORTS 如果當(dāng)前上下文存在事務(wù),則支持事務(wù)加入事務(wù),如果不存在事務(wù),則使用非事務(wù)的方式執(zhí)行。

MANDATORY 如果當(dāng)前上下文中存在事務(wù),否則拋出異常。

REQUIRES_NEW 每次都會(huì)新建一個(gè)事務(wù),并且同時(shí)將上下文中的事務(wù)掛起,執(zhí)行當(dāng)前新建事務(wù)完成以后,上下文事務(wù)恢復(fù)再執(zhí)行。

NOT_SUPPORTED 如果當(dāng)前上下文中存在事務(wù),則掛起當(dāng)前事務(wù),然后新的方法在沒有事務(wù)的環(huán)境中執(zhí)行。

NEVER 如果當(dāng)前上下文中存在事務(wù),則拋出異常,否則在無事務(wù)環(huán)境上執(zhí)行代碼。

NESTED 如果當(dāng)前上下文中存在事務(wù),則嵌套事務(wù)執(zhí)行,如果不存在事務(wù),則新建事務(wù)。

如果我們?cè)谑謩?dòng)設(shè)置propagation參數(shù)的時(shí)候,把傳播特性設(shè)置錯(cuò)了,比如:

@Service
publicclassOrderServiceImpl{

@Transactional(propagation=Propagation.NEVER)
publicvoidcancelOrder(UserModeluserModel){
//取消訂單
cancelOrder(orderDTO);
//還原庫(kù)存
restoreProductStock(orderDTO.getProductId(),orderDTO.getProductCount());
}
}

我們可以看到cancelOrder()方法的事務(wù)傳播特性定義成了Propagation.NEVER,這種類型的傳播特性不支持事務(wù),如果有事務(wù)則會(huì)拋異常。

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

在實(shí)際項(xiàng)目開發(fā)中,多線程的使用場(chǎng)景還是挺多的。如果Spring事務(wù)用在多線程場(chǎng)景中使用不當(dāng),也會(huì)導(dǎo)致事務(wù)無法生效。

@Slf4j
@Service
publicclassOrderServiceImpl{

@Autowired
privateOrderMapperorderMapper;
@Autowired
privateMessageServicemessageService;

@Transactional
publicvoidorderCommit(orderModelorderModel)throwsException{
orderMapper.insertOrder(orderModel);
newThread(()->{
messageService.sendSms();
}).start();
}
}

@Service
publicclassMessageService{

@Transactional
publicvoidsendSms(){
//發(fā)送短信
}
}

通過示例,我們可以看到訂單提交的事務(wù)方法orderCommit()中,調(diào)用了發(fā)送短信的事務(wù)方法sendSms(),但是發(fā)送短信的事務(wù)方法sendSms()是另起了一個(gè)線程調(diào)用的。

這樣會(huì)導(dǎo)致兩個(gè)方法不在同一個(gè)線程中,從而是兩個(gè)不同的事務(wù)。如果是sendSms()方法中拋了異常,orderCommit()方法也回滾是不可能的。

實(shí)際上,Spring的事務(wù)是通過ThreadLocal來保證線程安全的,事務(wù)和當(dāng)前線程綁定,多個(gè)線程自然會(huì)讓事務(wù)失效。

d49a85c6-9640-11ee-8b88-92fbcf53809c.jpg

2 總結(jié)

本篇文章主要是介紹Spring事務(wù)傳播特性,闡明了@Transactional注解屬性的使用方式,通過不同的代碼示例演示了Spring事務(wù)失效的常見場(chǎng)景。

審核編輯:湯梓紅

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

    關(guān)注

    33

    文章

    9441

    瀏覽量

    156077
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4940

    瀏覽量

    73083
  • spring
    +關(guān)注

    關(guān)注

    0

    文章

    341

    瀏覽量

    15763
  • 編程模型
    +關(guān)注

    關(guān)注

    0

    文章

    8

    瀏覽量

    1487

原文標(biāo)題:Spring 事務(wù)失效的十種常見場(chǎng)景

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

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

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

    這些操作。 spring事務(wù)有編程式事務(wù)和聲明式事務(wù)實(shí)現(xiàn)方式。編程式事務(wù)是通過編寫代碼來管理
    的頭像 發(fā)表于 11-08 10:10 ?1425次閱讀
    <b class='flag-5'>Spring</b><b class='flag-5'>事務(wù)</b>實(shí)現(xiàn)原理

    十種精密全波整流電路

    十種精密全波整流電路
    發(fā)表于 08-09 15:09

    請(qǐng)問怎么做一個(gè)跑馬燈有十種模式,第十種模式有三音樂,可加速減速和無線遙控?

    我現(xiàn)在想做一個(gè)跑馬燈,這個(gè)跑馬燈有十種模式,第十種模式要求有三音樂。,還得有數(shù)碼管顯示第幾種模式??梢詿o線遙控。求哪位大神可以幫我。小女子必有重謝。
    發(fā)表于 07-19 04:49

    Spring的兩方式事務(wù)管理和API接口介紹

    Spring事務(wù)管理
    發(fā)表于 03-21 06:52

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

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

    詳解Spring事務(wù)管理

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

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

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

    十種精密全波整流電路原圖分享

    十種精密全波整流電路原圖,大家點(diǎn)評(píng)下
    發(fā)表于 11-27 06:47

    十種方法能保護(hù)云數(shù)據(jù)安全

    十種方法能保護(hù)云數(shù)據(jù)安全
    發(fā)表于 01-14 12:00 ?12次下載

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

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

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

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

    十種常見的濾波器分享

    運(yùn)算放大器可以用于設(shè)計(jì)各種類型的濾波器,以下是十種常見的濾波器: 1. 低通濾波器:能夠通過讓低于截止頻率的信號(hào)通過,而抑制高于截止頻率的信號(hào)。
    的頭像 發(fā)表于 04-24 10:44 ?7498次閱讀

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

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

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

    對(duì)于從事java開發(fā)工作的同學(xué)來說,spring事務(wù)肯定再熟悉不過了。 在某些業(yè)務(wù)場(chǎng)景下,如果一個(gè)請(qǐng)求中,需要同時(shí)寫入多張表的數(shù)據(jù)。為了保證操作的原子性(要么同時(shí)成功,要么同時(shí)失敗),避免數(shù)據(jù)
    的頭像 發(fā)表于 10-08 14:27 ?882次閱讀
    <b class='flag-5'>spring</b><b class='flag-5'>事務(wù)</b><b class='flag-5'>失效</b>的一些<b class='flag-5'>場(chǎng)景</b>

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

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