国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【Spring】深入理解 Spring 事務(wù)及其傳播機制

這篇具有很好參考價值的文章主要介紹了【Spring】深入理解 Spring 事務(wù)及其傳播機制。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。


一、Spring 事務(wù)是什么

在 Spring 框架中,事務(wù)(Transaction)是一種用于管理數(shù)據(jù)庫操作的機制,旨在確保數(shù)據(jù)的一致性、可靠性和完整性。事務(wù)可以將一組數(shù)據(jù)庫操作(如插入、更新、刪除等)視為一個單獨的執(zhí)行單元,要么全部成功地執(zhí)行,要么全部回滾。這樣可以確保數(shù)據(jù)庫在任何時候都保持一致的狀態(tài),即使在發(fā)生故障或錯誤時也能保持?jǐn)?shù)據(jù)的完整性。

Spring 框架通過提供事務(wù)管理功能,使開發(fā)者能夠更輕松地管理事務(wù)的邊界。Spring 主要提供了兩種主要的事務(wù)管理方式:

  1. 編程式事務(wù)管理:通過編寫代碼顯式地管理事務(wù)的開始、提交和回滾操作。這種方式提供了更大的靈活性,但也需要更多的代碼維護。

  2. 聲明式事務(wù)管理:通過在配置中聲明事務(wù)的行為,由 Spring 框架自動處理事務(wù)的邊界,減少了開發(fā)者的工作量,并提高了代碼的可維護性。

二、Spring 中事務(wù)的實現(xiàn)方法

2.1 Spring 編程式事務(wù)(手動)

2.1.1 編程式事務(wù)的使用演示

在 Spring 中,編程式事務(wù)管理是一種手動控制事務(wù)邊界的方式,與 MySQL 操作事務(wù)的方法類似,它涉及三個重要的操作步驟:

  1. 開啟事務(wù)(獲取事務(wù)):首先需要通過獲取事務(wù)管理器(例如 DataSourceTransactionManager)來獲取一個事務(wù),從而開始一個新的事務(wù)。事務(wù)管理器是用于管理事務(wù)的核心組件。

  2. 提交事務(wù):一旦一組數(shù)據(jù)庫操作成功執(zhí)行,并且希望將這些更改永久保存到數(shù)據(jù)庫中,就可以調(diào)用事務(wù)對象的提交方法。這將使得事務(wù)中的所有操作都被應(yīng)用到數(shù)據(jù)庫。

  3. 回滾事務(wù):如果在事務(wù)處理過程中發(fā)生錯誤或某種條件不滿足,就可以調(diào)用事務(wù)對象的回滾方法,從而撤銷事務(wù)中的所有操作,回到事務(wù)開始前的狀態(tài)。

在 Spring Boot 中,可以利用內(nèi)置的事務(wù)管理器 DataSourceTransactionManager 來獲取事務(wù),提交或回滾事務(wù)。此外,TransactionDefinition 是用來定義事務(wù)的屬性的,當(dāng)獲取事務(wù)時需要將 TransactionDefinition 傳遞進DataSourceTransactionManager以獲取一個事務(wù)狀態(tài) TransactionStatus

例如,下面的代碼演示了編程式事務(wù):

@RestController
@RequestMapping("/user")
public class UserController {

    // 編程式事務(wù)
    @Autowired
    private DataSourceTransactionManager dataSourceTransactionManager;

    @Autowired
    private TransactionDefinition transactionDefinition;

    @Autowired
    private UserService userService;

    @RequestMapping("/del")
    public int delById(@RequestParam("id") Integer id) {
        if (id == null || id < 0) return 0;
        // 1. 開啟事務(wù)
        TransactionStatus transactionStatus = null;
        int res = 0;
        try {
            transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);

            // 2. 業(yè)務(wù)操作 —— 刪除用戶
            res = userService.delById(id);
            System.out.println("刪除: " + res);

            // 3. 提交、回滾事務(wù)
            // 提交事務(wù)
            dataSourceTransactionManager.commit(transactionStatus);
        } catch (Exception e) {
            e.printStackTrace();

            // 回滾事務(wù)
            if (transactionStatus != null) {
                dataSourceTransactionManager.rollback(transactionStatus);
            }
        }
        return res;
    }
}

這段代碼展示了如何通過編程式事務(wù)管理在Spring Boot中處理用戶刪除操作。編程式事務(wù)允許我們在代碼中明確地控制事務(wù)的邊界,以及在需要時手動提交或回滾事務(wù)。

2.1.2 編程式事務(wù)存在的問題

通過上面的示例代碼可以發(fā)現(xiàn),編程式事務(wù)雖然提供了更大的靈活性,但也存在一些問題和挑戰(zhàn):

  1. 代碼冗余和可讀性差: 編程式事務(wù)需要在代碼中顯式地添加事務(wù)管理的邏輯,導(dǎo)致代碼變得冗余且難以維護。每次需要使用事務(wù)的地方都需要重復(fù)編寫事務(wù)開啟、提交和回滾的代碼,降低了代碼的可讀性。

  2. 事務(wù)邊界控制復(fù)雜: 開發(fā)者需要手動管理事務(wù)的邊界,確保事務(wù)的開始、提交和回滾都在正確的位置。這可能會導(dǎo)致遺漏事務(wù)管理的代碼,從而影響數(shù)據(jù)的一致性。

  3. 事務(wù)傳播和嵌套問題: 在涉及多個方法調(diào)用的場景中,手動控制事務(wù)的傳播和嵌套關(guān)系可能變得復(fù)雜。需要開發(fā)者確保事務(wù)在各個方法間正確傳播,同時處理好嵌套事務(wù)的問題。

  4. 異常處理繁瑣: 編程式事務(wù)需要在異常處理時手動進行回滾操作,如果異常處理不當(dāng),事務(wù)可能無法正確回滾,導(dǎo)致數(shù)據(jù)不一致。

  5. 可維護性差: 隨著項目的發(fā)展,業(yè)務(wù)邏輯可能會變得更加復(fù)雜,可能需要頻繁地修改事務(wù)管理的代碼。這會增加代碼維護的難度,可能導(dǎo)致錯誤的引入。

  6. 不利于橫向擴展: 編程式事務(wù)難以支持橫向擴展,因為事務(wù)管理的代碼緊耦合在業(yè)務(wù)邏輯中,擴展時可能需要修改大量代碼。

相比之下,聲明式事務(wù)管理通過在方法上添加注解或在配置文件中進行聲明,使事務(wù)管理與業(yè)務(wù)邏輯分離,提供了更好的代碼組織和可維護性。聲明式事務(wù)可以在切面中自動處理事務(wù)的開始、提交和回滾,從而減輕了開發(fā)者的工作負(fù)擔(dān)。

所以,大多數(shù)情況下,建議使用聲明式事務(wù)管理來處理事務(wù),特別是在簡化事務(wù)邏輯和提高代碼可讀性方面更加有效。

2.2 Spring 聲明式事務(wù)(自動)

聲明式事務(wù)的實現(xiàn)非常簡單,只需要在需要的方法上添加 @Transactional 注解就可以輕松實現(xiàn),無需手動開啟或提交事務(wù)。

  • 當(dāng)進入被注解的方法時,Spring 會自動開啟一個事務(wù)。
  • 方法執(zhí)行完成后,如果沒有拋出未捕獲的異常,事務(wù)會自動提交,保證數(shù)據(jù)的一致性。
  • 然而,如果方法在執(zhí)行過程中發(fā)生了未經(jīng)處理的異常,事務(wù)會自動回滾,以確保數(shù)據(jù)庫的完整性和一致性。

這種方式大大簡化了事務(wù)管理的編碼,減少了手動處理事務(wù)的繁瑣操作,提高了代碼的可讀性和可維護性。例如下面的代碼實現(xiàn):

@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;

    // 聲明式事務(wù)
    @RequestMapping("/del")
    @Transactional
    public int delById(Integer id) {
        if (id == null || id < 0) return 0;
        int result = userService.delById(id);
        return result;
    }
}

在這個示例中,delById 方法使用了 @Transactional 注解,表示該方法需要受到聲明式事務(wù)的管理。在這個方法內(nèi)部,首先檢查了傳入的 id,如果為負(fù)數(shù)則直接返回結(jié)果。然后,調(diào)用了 userService.delById(id) 方法,刪除了指定用戶。在方法結(jié)束時,事務(wù)會自動提交。

同時,如果在執(zhí)行過程中發(fā)生了未處理的異常,事務(wù)將會自動回滾,以保持?jǐn)?shù)據(jù)庫的一致性。這種方式簡化了事務(wù)管理,提高了代碼的可讀性和可維護性。

2.2.1 @Transactional 作用范圍

@Transactional 注解可以被用來修飾方法或類:

  • 當(dāng)修飾方法時:需要注意它只能應(yīng)用到 public 訪問修飾符的方法上,否則注解不會生效。通常推薦在方法級別使用 @Transactional

  • 當(dāng)修飾類時:表示該注解對于類中所有的 public 方法都會生效。如果在類級別添加了 @Transactional,那么該類中所有的公共方法都將自動應(yīng)用事務(wù)管理。

一般來說,推薦將 @Transactional 注解應(yīng)用在方法級別,以便更精確地控制事務(wù)的范圍,從而避免不必要的事務(wù)開銷。如果類中的所有方法都需要事務(wù)管理,那么將注解應(yīng)用在類級別是一個更方便的選擇。

2.2.2 @Transactional 參數(shù)說明

通過查看 @Transactional 的源碼,可以發(fā)現(xiàn)它支持多個參數(shù),用來配置事務(wù)的行為。
【Spring】深入理解 Spring 事務(wù)及其傳播機制,Java EE,spring,java,Spring事務(wù),事務(wù)傳播機制

以下是對其中參數(shù)說明:

參數(shù)名稱 類型 默認(rèn)值 描述
value String “” 事務(wù)管理器的名稱,與 transactionManager 等效。
transactionManager String “” 事務(wù)管理器的名稱,與 value 等效。
label String[] 空數(shù)組 事務(wù)標(biāo)簽,暫無具體用途。
propagation Propagation Propagation.REQUIRED 事務(wù)的傳播行為,默認(rèn)為 REQUIRED。
isolation Isolation Isolation.DEFAULT 事務(wù)的隔離級別,默認(rèn)為數(shù)據(jù)庫默認(rèn)隔離級別。
timeout int -1 事務(wù)的超時時間,單位為秒。-1 表示沒有超時限制。
timeoutString String “” 事務(wù)的超時時間的字符串表示,與 timeout 等效。
readOnly boolean false 是否將事務(wù)設(shè)置為只讀,默認(rèn)為 false。
rollbackFor Class<? extends Throwable>[] 空數(shù)組 觸發(fā)回滾的異常類型。
rollbackForClassName String[] 空數(shù)組 觸發(fā)回滾的異常類型的類名字符串。
noRollbackFor Class<? extends Throwable>[] 空數(shù)組 不觸發(fā)回滾的異常類型。
noRollbackForClassName String[] 空數(shù)組 不觸發(fā)回滾的異常類型的類名字符串。

這些參數(shù)提供了對事務(wù)行為的靈活配置,可以根據(jù)具體業(yè)務(wù)需求來調(diào)整事務(wù)的傳播、隔離、超時和回滾策略等。

2.2.3 @Transactional 捕獲異常時回滾失效問題

針對于上述的實例代碼,現(xiàn)在代碼中間模擬實現(xiàn)一個異常,觀察會出現(xiàn)什么情況:

@RequestMapping("/del")
@Transactional
public int delById(Integer id) {
    if (id == null || id < 0) return 0;
    int result = userService.delById(id);
    System.out.println(result);
    try {
        int num = 10 / 0;
    } catch (Exception e) {
        // 如果直接處理異常,則不會回滾
      	e.printStackTrace();
    }
    return result;
}

通過瀏覽器訪問,發(fā)現(xiàn)服務(wù)器成功捕獲了異常:
【Spring】深入理解 Spring 事務(wù)及其傳播機制,Java EE,spring,java,Spring事務(wù),事務(wù)傳播機制
但是事務(wù)卻沒有回滾,對應(yīng)的用戶數(shù)據(jù)還是被刪除了:
【Spring】深入理解 Spring 事務(wù)及其傳播機制,Java EE,spring,java,Spring事務(wù),事務(wù)傳播機制
其原因在于:

在異常處理中直接捕獲了異常并進行了處理,從而導(dǎo)致事務(wù)回滾失效。默認(rèn)情況下,@Transactional 注解會在方法內(nèi)拋出 RuntimeException 及其子類異常時觸發(fā)事務(wù)回滾。然而,當(dāng)自己在 catch 塊內(nèi)捕獲異常并處理時,Spring 無法感知到異常,從而無法觸發(fā)事務(wù)回滾。

解決方法:

對于這個問題的解決方法大致可以分為兩種:

  1. 將捕獲的異常再次拋出:
e.printStackTrace();
throw e;

這種方法通過重新拋出異常,使得 Spring 能夠捕獲異常并觸發(fā)事務(wù)回滾。在異常發(fā)生后,事務(wù)將被回滾,確保之前的數(shù)據(jù)庫操作不會生效,從而保持?jǐn)?shù)據(jù)的一致性。

  1. 使用 TransactionAspectSupport 手動回滾事務(wù):
e.printStackTrace();
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

這種方法利用了 Spring 提供的 TransactionAspectSupport 類來手動設(shè)置事務(wù)回滾狀態(tài)。在捕獲異常后,通過調(diào)用 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(),可以將當(dāng)前事務(wù)設(shè)置為回滾狀態(tài),從而達到回滾事務(wù)的效果。這種方法更加靈活,可以在需要的時候手動控制事務(wù)的回滾。

無論選擇哪種方法,都可以在異常發(fā)生時觸發(fā)事務(wù)回滾,保障數(shù)據(jù)的完整性和一致性。選擇哪種方法取決于具體的代碼邏輯和需求。

2.4.4 @Transactional 工作原理

@Transactional 注解的工作原理基于 Spring AOP(面向切面編程)和事務(wù)管理器。它利用了 Spring 框架的代理機制來實現(xiàn)事務(wù)管理。

當(dāng)一個被 @Transactional 注解修飾的方法被調(diào)用時,Spring 會創(chuàng)建一個代理對象來包裝這個方法。代理對象會在方法執(zhí)行之前和之后添加事務(wù)管理的邏輯,以確保事務(wù)的開始、提交和回滾。這個過程是通過 AOP 技術(shù)實現(xiàn)的。

【Spring】深入理解 Spring 事務(wù)及其傳播機制,Java EE,spring,java,Spring事務(wù),事務(wù)傳播機制

具體來說,以下是 @Transactional 注解的工作流程:
【Spring】深入理解 Spring 事務(wù)及其傳播機制,Java EE,spring,java,Spring事務(wù),事務(wù)傳播機制

  1. 事務(wù)代理的創(chuàng)建: Spring 在運行時會為每個被 @Transactional 注解修飾的類創(chuàng)建一個代理對象。這個代理對象會包含事務(wù)管理的邏輯。

  2. 方法調(diào)用: 當(dāng)調(diào)用一個被 @Transactional 注解修飾的方法時,實際上是通過代理對象來調(diào)用。

  3. 事務(wù)切面的觸發(fā): 在代理對象中,事務(wù)切面會在方法執(zhí)行前后被觸發(fā)。在方法執(zhí)行前,切面會開啟一個事務(wù);在方法執(zhí)行后,切面會根據(jù)方法的執(zhí)行情況決定是提交事務(wù)還是回滾事務(wù)。

  4. 事務(wù)管理器的使用: 切面會通過事務(wù)管理器來控制事務(wù)。事務(wù)管理器負(fù)責(zé)實際的事務(wù)管理操作,如開啟、提交和回滾事務(wù)。

  5. 事務(wù)控制: 如果方法正常執(zhí)行完畢,切面會通知事務(wù)管理器提交事務(wù)。如果方法在執(zhí)行過程中拋出異常,切面會通知事務(wù)管理器回滾事務(wù)。

總體來說,@Transactional 注解的工作原理是通過代理和切面來實現(xiàn)事務(wù)管理,將事務(wù)的控制與業(yè)務(wù)邏輯分離,使代碼更加模塊化和可維護。這也是聲明式事務(wù)管理的核心機制之一。

2.3 Spring 事務(wù)失效場景

在某些情況下,Spring 中的事務(wù)可能會失效,導(dǎo)致事務(wù)不生效或不按預(yù)期執(zhí)行。以下是一些可能導(dǎo)致事務(wù)失效的場景:

  1. public 修飾的方法: 默認(rèn)情況下,@Transactional 注解只對 public 訪問修飾符的方法起作用。如果你在非 public 方法上添加了 @Transactional 注解,事務(wù)可能不會生效。

  2. timeout 超時: 如果事務(wù)執(zhí)行的時間超過了設(shè)置的 timeout 值,事務(wù)可能會被強制回滾。這可能會導(dǎo)致事務(wù)不按預(yù)期執(zhí)行,特別是當(dāng)事務(wù)需要執(zhí)行較長時間的操作時。

  3. 代碼中有 try/catch 如果在方法內(nèi)部捕獲并處理了異常,Spring 將無法感知到異常,從而無法觸發(fā)事務(wù)回滾。這可能導(dǎo)致事務(wù)在異常發(fā)生時不會回滾。

  4. 調(diào)用類內(nèi)部帶有 @Transactional 的方法: 當(dāng)一個類內(nèi)部的方法被調(diào)用時,它的 @Transactional 注解可能不會生效。這是因為 Spring 默認(rèn)使用基于代理的事務(wù)管理,直接在類內(nèi)部調(diào)用方法不會經(jīng)過代理,從而事務(wù)管理可能不會生效。

@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;

    public int del(Integer id){
        return delById(id);
    }
    
    // 聲明式事務(wù)
    @RequestMapping("/del")
    @Transactional
    public int delById(Integer id) {
        if (id == null || id < 0) return 0;
        int result = userService.delById(id);
        return result;
    }
}
  1. 數(shù)據(jù)庫不支持事務(wù): 如果你的數(shù)據(jù)庫不支持事務(wù),例如使用了某些特殊的數(shù)據(jù)庫引擎,事務(wù)可能無法正常工作。在這種情況下,應(yīng)該確保使用支持事務(wù)的數(shù)據(jù)庫引擎。

三、事務(wù)的隔離級別

3.1 事務(wù)的特性回顧

在數(shù)據(jù)庫中,事務(wù)具有以下四個重要的特性,通常被稱為 ACID 特性:

  1. 原子性(Atomicity): 事務(wù)被視為一個不可分割的操作單元,要么全部執(zhí)行成功,要么全部失敗回滾。

  2. 一致性(Consistency): 事務(wù)使數(shù)據(jù)庫從一個一致的狀態(tài)轉(zhuǎn)變到另一個一致的狀態(tài),保證數(shù)據(jù)的完整性和一致性。

  3. 隔離性(Isolation): 并發(fā)執(zhí)行的事務(wù)之間應(yīng)該互不影響,每個事務(wù)都感覺自己在獨立地操作數(shù)據(jù)。

  4. 持久性(Durability): 一旦事務(wù)提交,其對數(shù)據(jù)庫的修改就應(yīng)該是永久性的,即使發(fā)生系統(tǒng)崩潰也不應(yīng)該丟失。

3.2 MySQL 的事務(wù)隔離級別

MySQL 支持以下四個事務(wù)隔離級別,用于控制多個事務(wù)之間的相互影響程度:

  1. 讀未提交(Read Uncommitted): 允許一個事務(wù)讀取另一個事務(wù)尚未提交的數(shù)據(jù)。這是最低的隔離級別,可能會導(dǎo)致臟讀、不可重復(fù)讀和幻讀的問題。

  2. 讀已提交(Read Committed): 允許一個事務(wù)只能讀取另一個事務(wù)已經(jīng)提交的數(shù)據(jù)。這可以避免臟讀,但可能會出現(xiàn)不可重復(fù)讀和幻讀的問題。

  3. 可重復(fù)讀(Repeatable Read): 保證在同一個事務(wù)中多次讀取同樣記錄的結(jié)果是一致的,即使其他事務(wù)對該記錄進行了修改。這可以避免臟讀和不可重復(fù)讀,但可能出現(xiàn)幻讀。

  4. 串行化(Serializable): 最高的隔離級別,確保每個事務(wù)都完全獨立運行,避免了臟讀、不可重復(fù)讀和幻讀問題,但可能影響并發(fā)性能。

以下是事務(wù)四個隔離級別對應(yīng)的臟讀、不可重復(fù)讀、幻讀情況:

隔離級別 臟讀 不可重復(fù)讀 幻讀
讀未提交
讀已提交 ×
可重復(fù)讀 × ×
串行化 × × ×
  • √ 表示可能出現(xiàn)該問題。
  • × 表示該問題不會出現(xiàn)。

3.3 Spring 事務(wù)的隔離級別

Spring 通過 @Transactional 注解中的 isolation 參數(shù)來支持不同的事務(wù)隔離級別。Isolation的源碼如下:

【Spring】深入理解 Spring 事務(wù)及其傳播機制,Java EE,spring,java,Spring事務(wù),事務(wù)傳播機制

可以使用這些枚舉值來設(shè)置隔離級別:

  • Isolation.DEFAULT:使用數(shù)據(jù)庫的默認(rèn)隔離級別。
  • Isolation.READ_UNCOMMITTED:讀未提交。
  • Isolation.READ_COMMITTED:讀已提交。
  • Isolation.REPEATABLE_READ:可重復(fù)讀。
  • Isolation.SERIALIZABLE:串行化。

例如,指定 Spring 事務(wù)的隔離級別為 DEFAULT

@RequestMapping("/del")
@Transactional(isolation = Isolation.DEFAULT)
public int delById(Integer id) {
    if (id == null || id < 0) return 0;
    int result = userService.delById(id);
    return result;
}

通過選擇合適的事務(wù)隔離級別,可以在并發(fā)環(huán)境中控制事務(wù)之間的相互影響程度,從而避免數(shù)據(jù)不一致的問題。不同的隔離級別在性能和數(shù)據(jù)一致性方面有不同的權(quán)衡,開發(fā)人員需要根據(jù)具體的業(yè)務(wù)需求來選擇合適的隔離級別。

四、Spring 事務(wù)的傳播機制

4.1 為什么需要事務(wù)傳播機制

在復(fù)雜的應(yīng)用場景中,一個事務(wù)操作可能會調(diào)用多個方法或服務(wù)。這些方法可能需要獨立地進行事務(wù)管理,但又需要協(xié)同工作,以保持?jǐn)?shù)據(jù)的一致性和完整性。這時就需要引入事務(wù)傳播機制。

事務(wù)傳播機制定義了多個事務(wù)方法之間如何協(xié)同工作,如何共享同一個事務(wù),以及在嵌套事務(wù)中如何進行隔離和提交。通過事務(wù)傳播機制,可以確保多個事務(wù)方法在執(zhí)行時能夠按照一定的規(guī)則進行協(xié)調(diào),避免數(shù)據(jù)不一致的問題。

4.2 事務(wù)傳播機制的分類

Spring 定義了七種事務(wù)傳播行為,用于控制多個事務(wù)方法之間的交互。這些傳播行為可以在 @Transactional 注解中的 propagation 參數(shù)中進行設(shè)置。以下是這些傳播行為:

  1. REQUIRED(默認(rèn)): 如果當(dāng)前存在事務(wù),就加入到當(dāng)前事務(wù)中;如果沒有事務(wù),就創(chuàng)建一個新的事務(wù)。這是最常用的傳播行為。

  2. SUPPORTS: 如果當(dāng)前存在事務(wù),就加入到當(dāng)前事務(wù)中;如果沒有事務(wù),就以非事務(wù)方式執(zhí)行。

  3. MANDATORY: 如果當(dāng)前存在事務(wù),就加入到當(dāng)前事務(wù)中;如果沒有事務(wù),就拋出異常。

  4. REQUIRES_NEW: 無論當(dāng)前是否存在事務(wù),都創(chuàng)建一個新的事務(wù)。如果當(dāng)前存在事務(wù),則將當(dāng)前事務(wù)掛起。

  5. NOT_SUPPORTED: 以非事務(wù)方式執(zhí)行,如果當(dāng)前存在事務(wù),就將當(dāng)前事務(wù)掛起。

  6. NEVER: 以非事務(wù)方式執(zhí)行,如果當(dāng)前存在事務(wù),就拋出異常。

  7. NESTED: 如果當(dāng)前存在事務(wù),就在一個嵌套的事務(wù)中執(zhí)行;如果沒有事務(wù),就與 REQUIRED 一樣。

以上 7 種傳播行為,可以根據(jù)是否支持當(dāng)前事務(wù)分為以下 3 類:
【Spring】深入理解 Spring 事務(wù)及其傳播機制,Java EE,spring,java,Spring事務(wù),事務(wù)傳播機制

4.3 Spring 事務(wù)傳播機制使用案例

REQUIRED 和 NESTED 傳播機制的事務(wù)演示:

控制層 ControllerUserController

@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @RequestMapping("/add") // /add?username=lisi&password=123456
    @Transactional(propagation = Propagation.NESTED)
    // Transactional(propagation = Propagation.REQUIRED)
    //@Transactional(propagation = Propagation.REQUIRES_NEW)
    public int add(@RequestParam("username") String username, @RequestParam("password") String password) {
        if (null == username || null == password || "".equals(username) || "".equals(password)) {
            return 0;
        }

        int result = 0;

        // 用戶添加操作
        UserInfo user = new UserInfo();
        user.setUsername(username);
        user.setPassword(password);

        result = userService.add(user);


        try {
            int num = 10 / 0; // 加入事務(wù):外部事務(wù)回滾,內(nèi)部事務(wù)也會回滾
        } catch (Exception e) {
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }

        return result;
    }
}

服務(wù)層ServiceUserService

@Service
public class UserService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private LogService logService;

    public int delById(Integer id){
        return userMapper.delById(id);
    }

    @Transactional(propagation = Propagation.NESTED)
    // Transactional(propagation = Propagation.REQUIRED)
    //@Transactional(propagation = Propagation.REQUIRES_NEW)
    public int add(UserInfo user){
        // 添加用戶信息
        int addUserResult = userMapper.add(user);
        System.out.println("添加用戶結(jié)果:" + addUserResult);

        //添加日志信息
        Log log = new Log();
        log.setMessage("添加用戶信息");
        logService.add(log);

        return addUserResult;
    }
}

服務(wù)層ServiceLogService

@Service
public class LogService {
    @Autowired
    private LogMapper logMapper;

    @Transactional(propagation = Propagation.NESTED)
    // Transactional(propagation = Propagation.REQUIRED)
    //@Transactional(propagation = Propagation.REQUIRES_NEW)
    public int add(Log log){
        int result =  logMapper.add(log);
        System.out.println("添加日志結(jié)果:" + result);
        // 模擬異常情況
        try {
            int num = 10 / 0;
        } catch (Exception e) {
            // 加入事務(wù):內(nèi)部事務(wù)回滾,外部事務(wù)也會回滾,并且會拋異常
            // 嵌套事務(wù):內(nèi)部事務(wù)回滾,不影響外部事務(wù)
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
        return result;
    }
}

在事務(wù)傳播機制中,REQUIREDNESTED 是兩種不同的傳播行為,它們在事務(wù)的嵌套、回滾以及對外部事務(wù)的影響等方面有所不同。通過上面代碼的演示,可以得出 REQUIREDNESTED 之間的主要區(qū)別如下:

  1. 嵌套性質(zhì):

    • REQUIRED:內(nèi)部方法與外部方法共享同一個事務(wù),內(nèi)部方法的事務(wù)操作是外部方法事務(wù)的一部分。
    • NESTED:內(nèi)部方法創(chuàng)建一個嵌套事務(wù),它是外部事務(wù)的子事務(wù),具有獨立的事務(wù)狀態(tài),內(nèi)部事務(wù)的回滾不會影響外部事務(wù)。
  2. 回滾行為:

    • REQUIRED:如果內(nèi)部方法拋出異?;蛟O(shè)置回滾,會導(dǎo)致整個外部事務(wù)回滾,包括內(nèi)部方法和外部方法的操作。
    • NESTED:如果內(nèi)部方法拋出異?;蛟O(shè)置回滾,只會回滾內(nèi)部事務(wù),而外部事務(wù)仍然可以繼續(xù)執(zhí)行。
  3. 影響外部事務(wù):

    • REQUIRED:內(nèi)部方法的事務(wù)操作會影響外部事務(wù)的狀態(tài),內(nèi)部方法回滾會導(dǎo)致外部事務(wù)回滾。
    • NESTED:內(nèi)部方法的事務(wù)操作不會影響外部事務(wù)的狀態(tài),內(nèi)部方法回滾不會影響外部事務(wù)的提交或回滾。
  4. 支持性:

    • REQUIRED:較為常用,適用于將多個方法的操作作為一個整體進行事務(wù)管理的情況。
    • NESTED:在某些數(shù)據(jù)庫中不支持,需要數(shù)據(jù)庫支持保存點(Savepoint)的功能。

總的來說,REQUIRED 適用于需要將多個方法的操作作為一個整體事務(wù)管理的情況,而 NESTED 適用于需要在內(nèi)部方法中創(chuàng)建嵌套事務(wù)的情況,保持內(nèi)部事務(wù)的獨立性,不影響外部事務(wù)。選擇使用哪種傳播行為取決于業(yè)務(wù)需求和數(shù)據(jù)庫的支持情況。文章來源地址http://www.zghlxwxcb.cn/news/detail-651856.html

到了這里,關(guān)于【Spring】深入理解 Spring 事務(wù)及其傳播機制的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • Spring事務(wù)和事務(wù)傳播機制(1)

    Spring事務(wù)和事務(wù)傳播機制(1)

    ??????SSM專欄更新中,各位大佬覺得寫得不錯,支持一下,感謝了!?????? Spring + Spring MVC + MyBatis_冷兮雪的博客-CSDN博客 在Spring框架中,事務(wù)管理是一種用于維護數(shù)據(jù)庫操作的一致性和完整性的機制。Spring事務(wù)管理提供了靈活的方式來處理事務(wù),包括事務(wù)的創(chuàng)建

    2024年02月12日
    瀏覽(26)
  • Spring—事務(wù)及事務(wù)的傳播機制

    Spring—事務(wù)及事務(wù)的傳播機制

    將一組操作封裝成一個執(zhí)行單元, 即這一組操作一同成功 / 一同失敗 舉個栗子?? 未使用事務(wù) 滑稽老哥給女神轉(zhuǎn)賬 520 由于某種原因, 女神并未收到轉(zhuǎn)賬的 520, 而滑稽老哥卻被扣款 520 使用事務(wù) 滑稽老哥給女神轉(zhuǎn)賬 520 由于某種原因, 女神并未收到轉(zhuǎn)賬的 520 因為使用事務(wù), 所以

    2024年02月13日
    瀏覽(23)
  • Spring事務(wù)的四大特性+事務(wù)的傳播機制+隔離機制

    Spring事務(wù)的四大特性+事務(wù)的傳播機制+隔離機制

    原子性是指事務(wù)是一個不可分割的工作單位,事務(wù)中的操作要么都發(fā)生,要么都不發(fā)生。 事務(wù)是一個原子操作, 由一系列動作組成。 組成一個事務(wù)的多個數(shù)據(jù)庫操作是一個不可分割的原子單元 ,只有所有的操作執(zhí)行成功,整個事務(wù)才提交。 事務(wù)中的任何一個數(shù)據(jù)庫操作失敗

    2024年01月20日
    瀏覽(31)
  • Spring Boot 事務(wù)和事務(wù)傳播機制

    Spring Boot 事務(wù)和事務(wù)傳播機制

    事務(wù)定義 將一組操作封裝成一個執(zhí)行單元 (封裝到一起),這一組的執(zhí)行具備原子性, 那么就要么全部成功,要么全部失敗. 為什么要用事務(wù)? 比如轉(zhuǎn)賬分為兩個操作: 第一步操作:A 賬戶-100 元。 第二步操作:B賬戶 +100 元。 如果沒有事務(wù),第一步執(zhí)行成功了,第二步執(zhí)行失敗了,

    2024年02月11日
    瀏覽(25)
  • spring的事務(wù)傳播機制

    spring的事務(wù)傳播機制

    嫌棄內(nèi)容代碼復(fù)雜的可直接看思維導(dǎo)圖大綱即可 指的就是當(dāng)一個事務(wù)方法被另一個事務(wù)方法調(diào)用時,這個事務(wù)方法應(yīng)該如何進行 默認(rèn),當(dāng)前存在事務(wù),則加入該事務(wù);不存在事務(wù),創(chuàng)建新事務(wù)。 始終以新的事務(wù)運行,當(dāng)前存在事務(wù),則掛起原事務(wù);不存在事務(wù),創(chuàng)建新事務(wù)

    2023年04月23日
    瀏覽(39)
  • Spring事務(wù)傳播機制

    Spring事務(wù)傳播機制

    編程式事務(wù)管理:通過? TransactionTemplate 或者 TransactionManager 手動管理事務(wù),實際應(yīng)用中很少使用,這不是本文的重點,就不在這里贅述。 聲明式事務(wù)管理:使用場景最多,也是最推薦使用的方式,直接加上@Transactional注解即可。 @Transactional 注解是用于聲明事務(wù)性方法的注解

    2024年01月16日
    瀏覽(42)
  • Spring事務(wù)傳播機制解析

    在Java的Spring框架中,事務(wù)管理是保證應(yīng)用數(shù)據(jù)一致性和可靠性的關(guān)鍵。Spring提供了靈活的事務(wù)傳播機制,它定義了事務(wù)邊界,以及在嵌套方法調(diào)用時如何處理事務(wù)。本文旨在深入探討Spring的事務(wù)傳播行為,幫助開發(fā)者更好地理解和運用這一重要特性。 事務(wù)傳播機制指的是在

    2024年01月16日
    瀏覽(35)
  • 【JavaEE進階】Spring事務(wù)和事務(wù)傳播機制

    【JavaEE進階】Spring事務(wù)和事務(wù)傳播機制

    Spring 事務(wù)是 Spring 框架提供的一種機制,用于 管理數(shù)據(jù)庫操作或其他資源的一組相關(guān)操作 ,以確保它們在一個原子、一致、可靠和隔離的執(zhí)行單元內(nèi)進行。事務(wù)用于維護數(shù)據(jù)的完整性并支持并發(fā)訪問數(shù)據(jù)庫時的數(shù)據(jù)一致性。 Spring 事務(wù)的主要特點包括: 原子性(Atomicity):

    2024年02月09日
    瀏覽(22)
  • 一文詳解Spring事務(wù)傳播機制

    一文詳解Spring事務(wù)傳播機制

    目錄 背景 Spring事務(wù) @Transactional注解 使用場景 失效場景 原理 常用參數(shù) 注意 事務(wù)傳播機制 處理嵌套事務(wù)流程 主事務(wù)為REQUIRED子事務(wù)為REQUIRED 主事務(wù)為REQUIRED子事務(wù)為REQUIRES_NEW 主事務(wù)為REQUIRED子事務(wù)為NESTED 實現(xiàn)方式 源碼解析 我們在使用Spring管理數(shù)據(jù)庫事務(wù)的時候很方便,只

    2023年04月26日
    瀏覽(21)
  • Spring事務(wù)傳播的7種機制

    Spring事務(wù)傳播的7種機制

    1. Propagation.REQUIRED:默認(rèn)的事務(wù)傳播級別,它表示如果當(dāng)前存在事務(wù),則加入該事務(wù);如果 當(dāng)前沒有事務(wù),則創(chuàng)建一個新的事務(wù)。 2. Propagation.SUPPORTS:如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒有事務(wù),則以非事務(wù)的 方式繼續(xù)運行。 3. Propagation.MANDATORY:(mandatory:強制

    2024年02月09日
    瀏覽(25)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包