Spring Boot 中事務的用法詳解

引言?

在 Spring Boot 中,事務管理是一個非常重要的功能,尤其是在涉及數據庫操作的業務場景中。Spring 提供了強大的事務管理支持,能夠幫助我們簡化事務的管理和控制。本文將詳細介紹 Spring Boot 中事務的用法,包括事務的基本概念、事務的配置、事務的傳播行為、事務的隔離級別以及事務的回滾機制。

1. 事務的基本概念

事務(Transaction)是指一組數據庫操作,這些操作要么全部成功,要么全部失敗。事務的四大特性(ACID)包括:

  • 原子性(Atomicity):事務中的所有操作要么全部成功,要么全部失敗。

  • 一致性(Consistency):事務執行前后,數據庫的狀態保持一致。

  • 隔離性(Isolation):多個事務并發執行時,彼此之間互不干擾。

  • 持久性(Durability):事務一旦提交,對數據庫的修改是永久性的。

在 Spring Boot 中,事務管理是通過?@Transactional?注解來實現的。

2. Spring Boot 中事務的配置

2.1 啟用事務管理

Spring Boot 默認已經集成了事務管理功能,只需要在配置類或啟動類上添加?@EnableTransactionManagement?注解即可啟用事務管理。

@SpringBootApplication
@EnableTransactionManagement // 啟用事務管理
public class MyApplication {public static void main(String[] args) {SpringApplication.run(MyApplication.class, args);}
}

2.2 配置數據源和事務管理器

Spring Boot 默認使用?DataSourceTransactionManager?作為事務管理器。如果你使用的是 Spring Data JPA,事務管理器會自動配置。

# application.yml
spring:datasource:url: jdbc:mysql://localhost:3306/mydbusername: rootpassword: rootdriver-class-name: com.mysql.cj.jdbc.Driver

3. 使用?@Transactional?注解

@Transactional?是 Spring 提供的事務管理注解,可以標注在類或方法上。標注在類上時,表示該類中的所有方法都啟用事務管理;標注在方法上時,表示該方法啟用事務管理。

@Service
public class UserService {@Autowiredprivate UserRepository userRepository;@Transactional // 開啟事務  表示該方法開啟了事務public void createUser(User user) {userRepository.save(user);}
}

3.2 事務的傳播行為

事務的傳播行為(Propagation)定義了事務方法之間的調用關系。Spring 提供了以下幾種傳播行為:

  • REQUIRED(默認):如果當前存在事務,則加入該事務;如果當前沒有事務,則創建一個新的事務。(適用于大多數業務場景,尤其是需要保證多個操作在同一個事務中執行的場景。 例如,訂單創建時需要同時更新訂單表和庫存表。)

  • REQUIRES_NEW:無論當前是否存在事務,都創建一個新的事務。(適用于需要獨立事務的場景,尤其是日志記錄、審計等操作。 例如,記錄操作日志時,即使主事務失敗,日志記錄仍然需要成功。)

  • SUPPORTS:如果當前存在事務,則加入該事務;如果當前沒有事務,則以非事務方式執行。(適用于不需要強制事務的場景,例如查詢操作。 例如,查詢用戶信息時,如果調用方有事務,則加入事務;如果沒有事務,則以非事務方式執行。)

  • NOT_SUPPORTED:以非事務方式執行操作,如果當前存在事務,則掛起該事務。(適用于不需要事務支持的場景,例如發送消息、調用外部接口等。 例如,發送短信通知時,不需要事務支持。)

  • MANDATORY:如果當前存在事務,則加入該事務;如果當前沒有事務,則拋出異常。(適用于強制要求調用方必須有事務的場景。 例如,某些核心業務邏輯必須在一個事務中執行。)

  • NEVER:以非事務方式執行操作,如果當前存在事務,則拋出異常。(適用于強制要求調用方不能有事務的場景。 例如,某些只讀操作或外部調用。)

  • NESTED:如果當前存在事務,則在嵌套事務內執行;如果當前沒有事務,則創建一個新的事務。(適用于需要部分回滾的場景。 例如,訂單創建時需要更新多個表,如果某個表更新失敗,只需要回滾該表的操作,而不影響其他表的操作。)

  • 示例:

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void updateUser(User user) {userRepository.save(user);
    }

    3.3 事務的隔離級別

    事務的隔離級別(Isolation)定義了事務之間的可見性。Spring 支持以下幾種隔離級別:

  • DEFAULT:使用數據庫的默認隔離級別。(適用于大多數通用場景,尤其是當你對數據庫的默認行為沒有特殊要求時。 如果你不確定應該選擇哪種隔離級別,可以使用 DEFAULT,讓數據庫根據其默認行為處理事務。)

  • READ_UNCOMMITTED:允許讀取未提交的數據變更,可能會導致臟讀、幻讀和不可重復讀。(適用于對數據一致性要求不高的場景,例如統計數據的讀取或日志記錄。 不適用于涉及資金、訂單等對數據一致性要求高的場景。)

  • READ_COMMITTED:只能讀取已提交的數據,可以避免臟讀,但可能會導致幻讀和不可重復讀。(適用于大多數業務場景,尤其是對數據一致性有一定要求但不需要嚴格隔離的場景。 例如,電商系統中的訂單查詢、用戶信息查詢等。)

  • REPEATABLE_READ:確保在同一事務中多次讀取同一數據時結果一致,可以避免臟讀和不可重復讀,但可能會導致幻讀。(適用于對數據一致性要求較高的場景,例如銀行系統中的賬戶余額查詢。 例如,在一個事務中多次讀取同一賬戶的余額時,確保結果一致。)

  • SERIALIZABLE:最高隔離級別,確保事務串行執行,可以避免臟讀、幻讀和不可重復讀(適用于對數據一致性要求極高的場景,例如金融系統中的資金清算、庫存管理等。 由于性能開銷較大,通常只在必要時使用。)

  • 示例:

    @Transactional(isolation = Isolation.READ_COMMITTED)
    public User getUserById(Long id) {return userRepository.findById(id).orElse(null);
    }

    3.4 事務的回滾機制

    默認情況下,Spring 會在方法拋出?RuntimeException?或?Error?時回滾事務。如果需要自定義回滾規則,可以通過?rollbackFor(哪些異常回滾)?和?noRollbackFor(哪些異常不會回滾)?屬性來指定。

    示例:

    @Transactional(rollbackFor = Exception.class) // 所有異常都回滾
    public void updateUser(User user) throws Exception {userRepository.save(user);if (user.getName() == null) {throw new Exception("用戶名不能為空"); // 拋出受檢異常}
    }

    4. 事務的嵌套與傳播行為

    在復雜的業務場景中,可能會存在事務方法調用事務方法的情況。此時,事務的傳播行為決定了事務的嵌套方式。

  • 4.1 嵌套事務示例

    @Service
    public class OrderService {@Autowiredprivate UserService userService;@Transactional  //一級事務public void createOrder(Order order) {// 保存訂單orderRepository.save(order);// 調用另一個事務方法userService.updateUser(order.getUser());}
    }@Service
    public class UserService {@Transactional(propagation = Propagation.REQUIRES_NEW) //二級事務public void updateUser(User user) {userRepository.save(user);}
    }

    在上面的示例中,createOrder?方法調用?updateUser?方法時,updateUser?方法會開啟一個新的事務。

5. 事務的注意事項(事務不生效的幾種情況)

  1. 事務方法的可見性

    • @Transactional?只能應用于?public?方法。如果應用于?private?或?protected?方法,事務將不會生效。Spring 的事務管理是基于代理模式實現的,代理對象只能攔截?public?方法。對于?private?或?protected?方法,Spring 無法生成代理,因此事務不會生效。

      @Service
      public class UserService {@Autowiredprivate UserRepository userRepository;// 正確:public 方法,事務生效@Transactionalpublic void createUser(User user) {userRepository.save(user);}// 錯誤:private 方法,事務不會生效@Transactionalprivate void updateUser(User user) {userRepository.save(user);}// 錯誤:protected 方法,事務不會生效@Transactionalprotected void deleteUser(Long userId) {userRepository.deleteById(userId);}
      }

  2. 事務的自我調用問題

    • 如果事務方法調用了同一個類中的另一個事務方法,事務的傳播行為可能不會生效。這是因為Spring 的代理對象只能攔截從外部調用的方法。如果事務方法在同一個類中調用另一個事務方法,實際上是直接調用目標方法,而不是通過代理對象調用,因此事務的傳播行為不會生效。

      @Service
      public class OrderService {@Autowiredprivate OrderRepository orderRepository;@Transactionalpublic void createOrder(Order order) {// 保存訂單orderRepository.save(order);// 調用另一個事務方法(自我調用)updateInventory(order.getProductId(), order.getQuantity());}@Transactional(propagation = Propagation.REQUIRES_NEW)public void updateInventory(Long productId, int quantity) {// 更新庫存邏輯}
      }

      在上面的示例中,createOrder?方法調用了?updateInventory?方法,但由于是自我調用,updateInventory?方法的事務傳播行為(REQUIRES_NEW)不會生效。

    • 解決方法:

    • 將事務方法拆分到不同的類中
      將?updateInventory?方法移到另一個服務類中,通過依賴注入調用。

      @Service
      public class OrderService {@Autowiredprivate OrderRepository orderRepository;@Autowiredprivate InventoryService inventoryService;@Transactionalpublic void createOrder(Order order) {// 保存訂單orderRepository.save(order);// 調用另一個服務類的事務方法inventoryService.updateInventory(order.getProductId(), order.getQuantity());}
      }@Service
      public class InventoryService {@Transactional(propagation = Propagation.REQUIRES_NEW)public void updateInventory(Long productId, int quantity) {// 更新庫存邏輯}
      }

  3. 事務的超時設置

    • 可以通過?@Transactional(timeout = 10)?設置事務的超時時間(單位為秒)。如果事務執行時間超過指定時間,事務將自動回滾。

      @Service
      public class ReportService {@Autowiredprivate ReportRepository reportRepository;@Transactional(timeout = 10) // 設置事務超時時間為 10 秒public void generateReport() {// 模擬耗時操作for (int i = 0; i < 1000000; i++) {reportRepository.save(new Report("Report " + i));}}
      }

      在上面的示例中,如果?generateReport?方法的執行時間超過 10 秒,事務將自動回滾。

?

6. 總結

Spring Boot 提供了強大的事務管理功能,通過?@Transactional?注解可以輕松實現事務的控制。在實際開發中,需要根據業務需求選擇合適的傳播行為和隔離級別,同時注意事務方法的可見性和自我調用問題。

通過本文的介紹,相信你已經掌握了 Spring Boot 中事務的基本用法。如果你有更多問題,歡迎在評論區留言討論!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/70546.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/70546.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/70546.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Java面試——Tomcat

優質博文&#xff1a;IT_BLOG_CN 一、Tomcat 頂層架構 Tomcat中最頂層的容器是Server&#xff0c;代表著整個服務器&#xff0c;從上圖中可以看出&#xff0c;一個Server可以包含至少一個Service&#xff0c;用于具體提供服務。Service主要包含兩個部分&#xff1a;Connector和…

第4章 信息系統架構(三)

4.3 應用架構 應用架構的主要內容是規劃出目標應用分層分域架構&#xff0c;根據業務架構規劃目標應用域、應用組和目標應用組件&#xff0c;形成目標應用架構邏輯視圖和系統視圖。從功能視角出發&#xff0c;闡述應用組件各自及應用架構整體上&#xff0c;如何實現組織的高階…

python小項目編程-中級(1、圖像處理)

目錄 圖像處理 實現 測試 unittest pytest 圖像處理 實現界面化操作&#xff0c;使用PIL庫實現簡單的圖像處理功能&#xff0c;如縮放&#xff08;設置縮放比例&#xff09;、旋轉和濾鏡、對比度調整、亮度調整、灰度圖、二值化圖&#xff08;二值圖如果使用的是彩色圖片需…

【Leetcode 每日一題】2209. 用地毯覆蓋后的最少白色磚塊

問題背景 給你一個下標從 0 0 0 開始的 二進制 字符串 f l o o r floor floor&#xff0c;它表示地板上磚塊的顏色。 f l o o r [ i ] floor[i] floor[i] 為 ‘0’ 表示地板上第 i i i 塊磚塊的顏色是 黑色 。 f l o o r [ i ] floor[i] floor[i] 為’1’ 表示地板上第 i …

Docker 性能優化指南

Docker 提供了強大的容器化功能&#xff0c;能夠幫助開發者在不同的環境中構建、測試和部署應用。然而&#xff0c;隨著容器化應用的不斷增長&#xff0c;Docker 容器可能會面臨一些性能瓶頸&#xff0c;影響其運行效率、資源占用和擴展能力。為了確保容器在生產環境中的高效運…

2025 WE DAY品牌日| 天璇II WE X7 Pro充電樁震撼發布,能效電氣開啟充電革命

隨著新能源產業的迅猛發展,充電樁作為電動汽車能量補給的重要基礎設施,正在成為市場關注的焦點。能效電氣作為充電樁領域的佼佼者,專注于研發高效、智能的充電解決方案,為電動汽車的普及與可持續發展鋪設了堅實的基礎。 2025年2月21日,能效電氣在深圳盛大舉辦了以“以創新 引未…

< OS 有關 > Ubuntu 24 SSH 服務器更換端口 in jp/us VPSs

原因&#xff1a; 兩臺 VPS 的 ssh 端口一直被密碼重試&#xff0c; us 這臺已經封了 632, jp 這臺兩周前清過一次 sqlite3 數據&#xff0c;現在贊到 1008 Fail2Ban 是使用 sqlite3 來記錄&#xff0c;數據量大后&#xff0c;硬盤的 I/O 會飆升&#xff0c;我有寫過一個 app…

MATLAB學習之旅:數據插值與曲線擬合

在MATLAB的奇妙世界里,我們已經走過了一段又一段的學習旅程。從基礎的語法和數據處理,到如今,我們即將踏入數據插值與曲線擬合這片充滿魅力的領域。這個領域就像是魔法中的藝術創作,能夠讓我們根據現有的數據點,構建出更加豐富的曲線和曲面,從而更好地理解和描述數據背后…

若依-@Excel新增注解numberFormat

Excel注解中原本的scale會四舍五入小數&#xff0c;導致進度丟失 想要的效果 顯示的時候保留兩個小數真正的數值是保留之前的數值 還原過程 若以中有一個專門的工具類&#xff0c;用來處理excel的 找到EXCEL導出方法exportExcel()找到writeSheet,寫表格的方法找到填充數據的方法…

LeetCode 熱題 100_搜索二維矩陣(64_74_中等_C++)(二分查找)(暴力破解法;Z字形查找;一次二分查找)

LeetCode 熱題 100_搜索二維矩陣&#xff08;64_74&#xff09; 題目描述&#xff1a;輸入輸出樣例&#xff1a;題解&#xff1a;解題思路&#xff1a;思路一&#xff08;暴力破解法&#xff09;&#xff1a;思路二&#xff08;Z字形查找&#xff09;&#xff1a;思路三&#x…

從CNN到Transformer:遙感影像目標檢測的技術演進(礦產勘探、精準農業、城市規劃、林業測量、軍事目標識別和災害評估等)

在遙感影像分析領域&#xff0c;目標檢測一直是研究熱點之一。隨著高分辨率對地觀測系統的不斷發展&#xff0c;遙感影像的分辨率和數據量呈爆發式增長&#xff0c;如何高效、準確地從海量數據中提取有用信息&#xff0c;成為了一個亟待解決的問題。近年來&#xff0c;深度學習…

【rt-thread】rt-thread 控制 led 的兩種方式

1. pin設備 #define LED_PIN 3int led(void) {rt_uint8_t count;rt_pin_mode(LED_PIN, PIN_MODE_OUTPUT); for(count 0 ; count < 10 ;count){ rt_pin_write(LED_PIN, PIN_HIGH);rt_kprintf("led on, count : %d %d\r\n", count, rt_pin_read(LED_PIN));…

Excell 代碼處理

文章目錄 Excell 代碼處理cvc格式xlsl格式小結 Excell 代碼處理 有時候要對excell進行分析&#xff0c;或者數據的導入導出&#xff0c;這個時候如果可以用代碼讀寫分析操作那么會方便很多 cvc格式 CSV&#xff08;Comma-Separated Values&#xff0c;逗號分隔值&#xff09;是…

新手小白如何挖掘cnvd通用漏洞之存儲xss漏洞(利用xss釣魚)

視頻教程和更多福利在我主頁簡介或專欄里 &#xff08;不懂都可以來問我 專欄找我哦&#xff09; 如果對你有幫助你可以來專欄找我&#xff0c;我可以無償分享給你對你更有幫助的一些經驗和資料哦 目錄&#xff1a; 一、XSS的三種類型&#xff1a; 二、XSS攻擊的危害&#x…

代碼隨想錄算法【Day52】

Day51 101. 孤島的總面積 思路 從周邊找到陸地然后 通過 dfs或者bfs 將周邊靠陸地且相鄰的陸地都變成海洋&#xff0c;然后再去重新遍歷地圖 統計此時還剩下的陸地 代碼 #include <iostream> #include <vector> using namespace std; int dir[4][2] {-1, 0, …

Python開源項目月排行 2024年12月

#2024年12月2025年1月21日1DeepSeek-Coder-V2一個開源的專家混合&#xff08;MoE&#xff09;代碼語言模型&#xff0c;其在代碼特定任務中的性能可與GPT4-Turbo相媲美。具體而言&#xff0c;DeepSeek-Coder-V2是在DeepSeek-V2的一個中間檢查點上進一步預訓練的&#xff0c;增加…

Resource not found: roslaunchROS path [0]=/opt/ros/noetic/share/ros

解決辦法&#xff1b; cd ~/catkin_ws rm -rf build/ devel/ catkin_make source devel/setup.bash sudo apt-get install ros-noetic-roslaunch 輸入roscore后

.NET + Vue3 的前后端項目在IIS的發布

目錄 一、發布準備 1、安裝 IIS 2、安裝 Windows Hosting Bundle&#xff08;.NET Core 托管捆綁包&#xff09; 3、安裝 IIS URL Rewrite 二、項目發布 1、后端項目發布 2、前端項目發布 3、將項目部署到 IIS中 三、網站配置 1、IP配置 2、防火墻配置 3、跨域配置…

指定定網卡名稱

一、PCIe網卡名稱指定 原理&#xff1a;利用udev規則匹配PCIe設備的硬件特征&#xff08;如總線位置、MAC地址等&#xff09;&#xff0c;覆蓋默認命名規則 4 。 步驟&#xff1a; 獲取設備信息&#xff1a; Bash udevadm info -a -p /sys/class/net/<原設備名> # 如e…

【python】解析自動化腳本文件并按照=測試周期=存儲記錄

【python】連接Jira獲取token以及jira對象 【python】解析自動化腳本文件并按照測試周期存儲記錄 【python】向Jira推送自動化用例執行成功 【python】向Jira測試計劃下&#xff0c;附件中增加html測試報告 將已編寫的自動化測試用例按照jira號解析出來&#xff0c;并按照測試計…