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

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

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

3天內不再提示

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

jf_ro2CN3Fa ? 來源:稀土掘金技術社區 ? 2023-12-11 15:03 ? 次閱讀

1 概述

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

但是,事務如果沒有被正確出,很有可能會導致事務的失效,帶來意想不到的數據不一致問題,隨后就是大量的人工接入查看和修復數據,該篇主要分享Spring事務在技術上的正確使用方式,避免因為事務處理不當導致業務邏輯產生大量偶發性BUG。

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

事務的傳播類型

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

isolation

該屬性用于設置底層數據庫的事務隔離級別,事務的隔離級別介紹:

//讀取未提交數據(會出現臟讀,不可重復讀)基本不使用
@Transactional(isolation=Isolation.READ_UNCOMMITTED)
//讀取已提交數據(會出現不可重復讀和幻讀)Oracle默認
@Transactional(isolation=Isolation.READ_COMMITTED)
//可重復讀(會出現幻讀)MySQL默認
@Transactional(isolation=Isolation.REPEATABLE_READ)
//串行化
@Transactional(isolation=Isolation.SERIALIZABLE)

@Transactionnal注解屬性

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

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

1. 事務方法未被Spring管理

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

publicclassProductServiceImplextendsServiceImplimplementsIProductService{

@Autowired
privateProductMapperproductMapper;

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

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

2. 方法使用final類型修飾

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

@Service
publicclassOrderServiceImpl{

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

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

Tips: 如果某個方法是static的,同樣無法通過動態代理將方法聲明為事務方法。

3. 非public修飾的方法

如果事務方式不是public修飾,此時Spring事務會失效,舉個例子:

@Service
publicclassProductServiceImplextendsServiceImplimplementsIProductService{

@Autowired
privateProductMapperproductMapper;

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

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

4. 同一個類中的方法相互調用

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

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

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

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

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

5. 方法的事務傳播類型不支持事務

如果內部方法的事務傳播類型為不支持事務的傳播類型,則內部方法的事務同樣會在Spring中失效,舉個例子:

@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);

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


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

6. 異常被內部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);

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

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

7. 數據庫不支持事務

Spring事務生效的前提是連接的數據庫支持事務,如果底層的數據庫都不支持事務,則Spring事務肯定會失效的,例如:使用MySQL數據庫,選用MyISAM存儲引擎,因為MyISAM存儲引擎本身不支持事務,因此事務毫無疑問會失效。

8. 未配置開啟事務

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

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

如果是以往的Spring MVC項目,如果沒有配置下面的代碼,Spring事務也不會生效,正常需要在applicationContext.xml文件中,手動配置事務相關參數,比如:

 








 




9. 錯誤的傳播特性

其實,我們在使用@Transactional注解時,是可以指定propagation參數的。

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

REQUIRED 如果當前上下文中存在事務,那么加入該事務,如果不存在事務,創建一個事務,這是默認的傳播屬性值。

SUPPORTS 如果當前上下文存在事務,則支持事務加入事務,如果不存在事務,則使用非事務的方式執行。

MANDATORY 如果當前上下文中存在事務,否則拋出異常。

REQUIRES_NEW 每次都會新建一個事務,并且同時將上下文中的事務掛起,執行當前新建事務完成以后,上下文事務恢復再執行。

NOT_SUPPORTED 如果當前上下文中存在事務,則掛起當前事務,然后新的方法在沒有事務的環境中執行。

NEVER 如果當前上下文中存在事務,則拋出異常,否則在無事務環境上執行代碼。

NESTED 如果當前上下文中存在事務,則嵌套事務執行,如果不存在事務,則新建事務。

如果我們在手動設置propagation參數的時候,把傳播特性設置錯了,比如:

@Service
publicclassOrderServiceImpl{

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

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

10. 多線程調用

在實際項目開發中,多線程的使用場景還是挺多的。如果Spring事務用在多線程場景中使用不當,也會導致事務無法生效。

@Slf4j
@Service
publicclassOrderServiceImpl{

@Autowired
privateOrderMapperorderMapper;
@Autowired
privateMessageServicemessageService;

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

@Service
publicclassMessageService{

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

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

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

實際上,Spring的事務是通過ThreadLocal來保證線程安全的,事務和當前線程綁定,多個線程自然會讓事務失效。

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

2 總結

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

審核編輯:湯梓紅

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

    關注

    33

    文章

    8596

    瀏覽量

    151145
  • 代碼
    +關注

    關注

    30

    文章

    4788

    瀏覽量

    68603
  • spring
    +關注

    關注

    0

    文章

    340

    瀏覽量

    14343
  • 編程模型
    +關注

    關注

    0

    文章

    8

    瀏覽量

    1397

原文標題:Spring 事務失效的十種常見場景

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

收藏 人收藏

    評論

    相關推薦

    Spring事務實現原理

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

    十種精密全波整流電路

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

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

    我現在想做一個跑馬燈,這個跑馬燈有十種模式,第十種模式要求有三音樂。,還得有數碼管顯示第幾種模式。可以無線遙控。求哪位大神可以幫我。小女子必有重謝。
    發表于 07-19 04:49

    Spring的兩方式事務管理和API接口介紹

    Spring事務管理
    發表于 03-21 06:52

    Spring事務分析的實現方式

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

    詳解Spring事務管理

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

    Spring事務管理詳解說明

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

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

    十種精密全波整流電路原圖,大家點評下
    發表于 11-27 06:47

    十種方法能保護云數據安全

    十種方法能保護云數據安全
    發表于 01-14 12:00 ?12次下載

    淺談Spring事務的那些坑

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

    淺談Spring事務底層原理

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

    十種常見的濾波器分享

    運算放大器可以用于設計各種類型的濾波器,以下是十種常見的濾波器: 1. 低通濾波器:能夠通過讓低于截止頻率的信號通過,而抑制高于截止頻率的信號。
    的頭像 發表于 04-24 10:44 ?6627次閱讀

    8個Spring事務失效場景介紹

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

    spring事務失效的一些場景

    對于從事java開發工作的同學來說,spring事務肯定再熟悉不過了。 在某些業務場景下,如果一個請求中,需要同時寫入多張表的數據。為了保證操作的原子性(要么同時成功,要么同時失敗),避免數據
    的頭像 發表于 10-08 14:27 ?447次閱讀
    <b class='flag-5'>spring</b><b class='flag-5'>事務</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>傳播性的相關知識
    主站蜘蛛池模板: 亚洲综合色网站| 黄色网址中文字幕| 婷婷丁香五月中文字幕| 在线播放你懂| 欧美伊人网| 天天插在线视频| 首页 亚洲 欧美 制服 丝腿| 色老成人精品视频在线观看| 高清一级做a爱视频免费| 高清在线观看视频| 性欧美性free| 成年人黄色大片大全| 2021国产精品| 天天欲色| 一级福利视频| 一区二区不卡视频| 欧美地区一二三区| 奇米色吧| 怡红院黄色| 国产精品成人在线播放| 五月激情啪啪| 视频在线色| 五月婷综合网| 九九热视频免费在线观看| 激情文学亚洲色图| 操www| 色一欲一性一乱一区二区三区| 亚色综合| 高h文男主又粗又狠| 国产免费人成在线视频视频| xxxx黄| 日本电影在线观看黄| 欧美极品bbbbⅹxxxx| 在线播放12p| bt天堂网www连接| 日本一区二区三区视频在线观看| 免费国产一区| 69国产视频| 欧美性video精品| 成人一级网站| 日本黄色影片|