最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot中事務失效的六個原因解析

 更新時間:2023年10月19日 09:27:03   作者:yfs1024  
這篇文章主要介紹了SpringBoot中事務失效的六個原因解析,由于Spring的事務是基于AOP的方式結(jié)合動態(tài)代理來實現(xiàn)的,因此事務方法一定要是public的,這樣才能便于被Spring做事務的代理和增強,需要的朋友可以參考下

SpringBoot中事務失效的原因

常見的事務失效原因包括如下六個:

1. 事務方法非public修飾

由于Spring的事務是基于AOP的方式結(jié)合動態(tài)代理來實現(xiàn)的。因此事務方法一定要是public的,這樣才能便于被Spring做事務的代理和增強。

而且,在Spring內(nèi)部也會有一個 org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource類,去檢查事務方法的修飾符:

@Nullable
 protected TransactionAttribute computeTransactionAttribute(
  Method method, @Nullable Class<?> targetClass) {
   // Don't allow non-public methods, as configured.
   if (allowPublicMethodsOnly() && 
  !Modifier.isPublic(method.getModifiers())) {
      return null;
   }

    // ... 略

   return null;
 }

2. 非事務方法調(diào)用事務方法

@Service
public class OrderService {
    
    public void createOrder(){
        // ... 準備訂單數(shù)據(jù)
        
        // 生成訂單并扣減庫存
        insertOrderAndReduceStock();
    }
    
    @Transactional
    public void insertOrderAndReduceStock(){
        // 生成訂單
        insertOrder();
        // 扣減庫存
        reduceStock();
    }
}

可以看到,insertOrderAndReduceStock方法是一個事務方法,肯定會被Spring事務管理。Spring會給OrderService類生成一個動態(tài)代理對象,對insertOrderAndReduceStock方法做增加,實現(xiàn)事務效果。

但是現(xiàn)在createOrder方法是一個非事務方法,在其中調(diào)用了insertOrderAndReduceStock方法,這個調(diào)用其實隱含了一個this.的前綴。也就是說,這里相當于是直接調(diào)用原始的OrderService中的普通方法,而非被Spring代理對象的代理方法。那事務肯定就失效了!

3. 事務方法的異常被捕獲了

異常被捕獲了但是沒有往外拋異常,所以事務沒有發(fā)現(xiàn)方法中出現(xiàn)錯誤,所以也就沒有回滾

 @Transactional
    public void createOrder(){
        // ... 準備訂單數(shù)據(jù)
        // 生成訂單
        insertOrder();
        // 扣減庫存
        reduceStock();
    }

    private void reduceStock() {
        try {
            // ...扣庫存
        } catch (Exception e) {
            // 處理異常
        }
    }

在這段代碼中,reduceStock方法內(nèi)部直接捕獲了Exception類型的異常,也就是說方法執(zhí)行過程中即便出現(xiàn)了異常也不會向外拋出。

而Spring的事務管理就是要感知業(yè)務方法的異常,當捕獲到異常后才會回滾事務。

現(xiàn)在事務被捕獲,就會導致Spring無法感知事務異常,自然不會回滾,事務就失效了。

4. 事務異常類型不對

@Transactional(rollbackFor = RuntimeException.class)
public void createOrder() throws IOException {
    // ... 準備訂單數(shù)據(jù)

    // 生成訂單
    insertOrder();
    // 扣減庫存
    reduceStock();

    throw new IOException();
}

Spring的事務管理默認感知的異常類型是RuntimeException,當事務方法內(nèi)部拋出了一個IOException時,不會被Spring捕獲,因此就不會觸發(fā)事務回滾,事務就失效了。

因此,當我們的業(yè)務中會拋出RuntimeException以外的異常時,應該通過@Transactional注解中的rollbackFor屬性來指定異常類型:

@Transactional(rollbackFor = Exception.class)

5.事務傳播行為不對

    @Transactional
    public void createOrder(){
        // 生成訂單
        insertOrder();
        // 扣減庫存
        reduceStock();
        throw new RuntimeException("業(yè)務異常");
    }

	@Transactional  // 默認的是如果當前沒有事務,自己創(chuàng)建事務,如果有事務則加入
    public void insertOrder() {
    
    }
	// 不管當前方法所在方法有沒有都開啟一個事務
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void reduceStock() {
        
    }

在示例代碼中,事務的入口是createOrder()方法,會開啟一個事務,可以成為外部事務。在createOrder()方法內(nèi)部又調(diào)用了insertOrder()方法和reduceStock()方法。這兩個都是事務方法。

不過,reduceStock()方法的事務傳播行為是REQUIRES_NEW,這會導致在進入reduceStock()方法時會創(chuàng)建一個新的事務,可以成為子事務。insertOrder()則是默認,因此會與createOrder()合并事務。

因此,當createOrder方法最后拋出異常時,只會導致insertOrder方法回滾,而不會導致reduceStock方法回滾,因為reduceStock是一個獨立事務。

所以,一定要慎用傳播行為,注意外部事務與內(nèi)部事務之間的關系。

6.沒有被Spring管理

即當前類沒有被SpringBoot掃描

第二種事務失效的解決方案:

上面的問題在于非事務方法中調(diào)用事務方法其中隱含了一個this.的前綴, 雖然當前方法的事務也被代理類生成了,但是因為默認關鍵字的原因,調(diào)用的還是原來的是沒有事務的方法.

所以我們現(xiàn)在要做的就是要找到被代理之后的類,然后再在方法中調(diào)用該方法

1)引入AspectJ依賴:

<!--aspecj-->
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
	<version>1.9.7</version>
</dependency>

2)暴露代理對象

在啟動類上添加注解,暴露代理對象:

3)使用代理對象

通過AopContext拿到當前類的代理對象,然后調(diào)用對應方法

// 返回值是Object
IUserCouponService userCouponService = (IUserCouponService) AopContext.currentProxy();
userCouponService.insertCouponAndCheck(userId, coupon, null);

(補充 )StringBoot中事務相關的接口

在Spring中有兩個和事務相關的接口

PlatformTransactionManager 平臺事務管理接口

作用; 對于不同的數(shù)據(jù)源采用不同的管理平臺, 常用的實現(xiàn)類如下

  • DataSourceTransactionManager:使用JDBC或MyBatis進行事務管理。適用于DataSource數(shù)據(jù)源。
  • HibernateTransactionManager:使用Hibernate進行事務管理。適用于Hibernate持久層框架。

TransactionDefinition 事務定義接口

TransactionDefinition 接口中定義了事務的描述相關的三類常量:

  • 事務隔離級別
  • 事務傳播行為
  • 事務默認超時時限

1. 事務隔離級別

  • DEFAULT : 采用DB默認的事務隔離級別.mysql中默認的是 REPEATABLE_READ (repeatable_read)
  • READ_UNCOMMITTED: 讀未提交 未解決任何并發(fā)問題
  • READ_COMMITTED: 讀已提交 解決了臟讀,存在不可重復讀和幻讀
  • REPETABLE_READ : 可重復讀,解決了臟讀,不可重復讀,存在幻讀
  • SERIALIZABLE :串行化.不存在并發(fā)問題

那么什么是臟讀, 幻讀和 不可重復讀呢?

臟讀(dirty read): 當一個事務讀取另一個事務尚未提交的修改時,產(chǎn)生臟讀

不可重復讀(nonrepeatable read):同一查詢在同一事務中多次進行,由于其他提交事務所做的修改或刪除,每次返回不同的結(jié)果集,此時發(fā)生不可重復讀

幻讀(phantom read):同一查詢在同一事務中多次進行,由于其他提交事務所做的插入操作,每次返回不同的結(jié)果集,此時發(fā)生幻讀

2. 事務的傳播行為

定義了七個事務的傳播行為:都是以 PROPAGATION_開頭 propagation(常用三個)

事務傳播行為是指,處于不同事務中的方法在相互調(diào)用時,執(zhí)行期間事務的維護情況

  • propagation_required (spring默認的傳播行為)
  • propagation_requires_new
  • propagation_supports

propagation_required :

說明:指定的方法必須在事務內(nèi)執(zhí)行。若當前存在事務,就加入到當前事務中;若當前沒有事務,則創(chuàng)建一個新事務。這種傳播行為是最常見的選擇,也是 Spring 默認的事務傳播行為。 

演示說明:

**如該傳播行為加在doOther()**方法上。若 doSome()方法在調(diào)用 doOther()方法時就是在事務內(nèi)運行的,則 doOther()方法的執(zhí)行也加入到該事務內(nèi)執(zhí)行。若 doSome()方法在調(diào)用 doOther()方法時沒有在事務內(nèi)執(zhí)行,則 doOther()方法會創(chuàng)建一個事務,并在其中執(zhí)行。

propagation_requires_new:

說明:總是新建一個事務,如當前存在事務,就將當前事務掛起,直到新事務執(zhí)行完畢

propagation_supports:

說明:指定的方法支持當前事務,但若當前沒有事務,也可以以非事務方法執(zhí)行

3. 事務超時時限

該值一般就是用默認值

到此這篇關于SpringBoot中事務失效的六個原因解析的文章就介紹到這了,更多相關SpringBoot事務失效原因內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Java JVM內(nèi)存區(qū)域詳解

    Java JVM內(nèi)存區(qū)域詳解

    下面小編就為大家?guī)硪黄趈vm java內(nèi)存區(qū)域的介紹。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2021-11-11
  • jvm-jstack常用的用法示例

    jvm-jstack常用的用法示例

    jstack 是一個常用的用于分析 Java 進程的工具。它可以顯示 Java 進程中所有線程狀態(tài)和堆棧信息,幫助定位 Java 進程中的問題,這篇文章主要介紹了jvm-jstack常用的用法示例,需要的朋友可以參考下
    2023-06-06
  • springboot實現(xiàn)返回視圖而不是string的方法

    springboot實現(xiàn)返回視圖而不是string的方法

    這篇文章主要介紹了springboot實現(xiàn)返回視圖而不是string的方法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • Springboot 整合 Java DL4J 實現(xiàn)智能客服功能

    Springboot 整合 Java DL4J 實現(xiàn)智能客服功能

    本文主要介紹了如何使用SpringBoot整合JavaDeeplearning4j來構(gòu)建一個智能客服系統(tǒng),詳細探討了神經(jīng)網(wǎng)絡選擇、數(shù)據(jù)集格式、技術介紹、Maven依賴、代碼示例等內(nèi)容,為構(gòu)建高效、便捷、個性化的客戶服務提供了理論支持和實踐指導
    2024-10-10
  • Java冒泡排序詳解(附有詳細代碼)

    Java冒泡排序詳解(附有詳細代碼)

    冒泡排序是一種簡單的排序算法,通過相鄰元素的比較和交換來實現(xiàn),它雖然在效率上不如其他排序算法,但在某些特定場景下仍然有其應用價值,這篇文章主要介紹了Java冒泡排序的相關資料,文中給出了詳細的代碼示例,需要的朋友可以參考下
    2025-04-04
  • Java讀取Properties文件時保持順序的解決過程

    Java讀取Properties文件時保持順序的解決過程

    文章講述了解決Java中Properties文件讀取時中文亂碼問題的幾種方法,包括重寫Properties的put方法、拓展記錄解決ResourceBundle讀取properties中文亂碼問題等
    2025-11-11
  • @RequestBody獲取不到參數(shù)的問題

    @RequestBody獲取不到參數(shù)的問題

    這篇文章主要介紹了@RequestBody獲取不到參數(shù)的問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • SpringBoot整合WebSocket實現(xiàn)后端向前端主動推送消息方式

    SpringBoot整合WebSocket實現(xiàn)后端向前端主動推送消息方式

    這篇文章主要介紹了SpringBoot整合WebSocket實現(xiàn)后端向前端主動推送消息方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • Java利用InputStream類實現(xiàn)文件讀取與處理

    Java利用InputStream類實現(xiàn)文件讀取與處理

    在Java開發(fā)中,輸入流(InputStream)是一個非常重要的概念,它涉及到文件讀寫、網(wǎng)絡傳輸?shù)榷鄠€方面,InputStream類是Java中輸入流的抽象基類,定義了讀取輸入流數(shù)據(jù)的方法,本文將以InputStream類為切入點,介紹Java中的輸入流概念及其應用,需要的朋友可以參考下
    2023-11-11
  • Java?設計模式以虹貓藍兔的故事講解簡單工廠模式

    Java?設計模式以虹貓藍兔的故事講解簡單工廠模式

    簡單工廠模式是屬于創(chuàng)建型模式,又叫做靜態(tài)工廠方法(Static Factory Method)模式,但不屬于23種GOF設計模式之一。簡單工廠模式是由一個工廠對象決定創(chuàng)建出哪一種產(chǎn)品類的實例。簡單工廠模式是工廠模式家族中最簡單實用的模式,可以理解為是不同工廠模式的一個特殊實現(xiàn)
    2022-03-03

最新評論

河池市| 武山县| 海盐县| 荔波县| 运城市| 鹤岗市| 西乡县| 通榆县| 阿尔山市| 石城县| 丁青县| 阆中市| 海南省| 兴海县| 双柏县| 共和县| 磐安县| 太康县| 延安市| 巴东县| 含山县| 昌邑市| 南汇区| 海城市| 海丰县| 江山市| 大足县| 灵丘县| 石柱| 卢湾区| 尼玛县| 昌都县| 安顺市| 嵊泗县| 容城县| 改则县| 衡山县| 泾阳县| 乌苏市| 林州市| 阳东县|