Spring Boot中的事務是如何實現的?懂嗎?

SpringBoot中的事務管理,用得好,能確保數據的一致性和完整性;用得不好,可能會給性能帶來不小的影響哦。

基本使用

在SpringBoot中,事務的使用非常簡潔。首先,得感謝Spring框架提供的@Transactional注解,這個小東西可以說是非常強大了。

讓我們先看一個基礎的例子:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;@Service
public class UserService {@Autowiredprivate UserRepository userRepository;@Transactionalpublic void createUser(String name) {User user = new User(name);userRepository.save(user);// 這里假設有其他的邏輯操作}
}

在這個例子中,我們通過@Transactional注解標記了createUser方法。這意味著,當這個方法被調用時,Spring會為我們自動創建一個事務。如果方法正常執行完畢,事務就會提交;如果遇到異常,事務就會回滾,確保數據的一致性。

最近無意間獲得一份阿里大佬寫的刷題筆記,一下子打通了我的任督二脈,進大廠原來沒那么難。

這是大佬寫的,?7701頁的BAT大佬寫的刷題筆記,讓我offer拿到手軟

開啟事務

雖然我們已經看到了如何使用@Transactional,但是你知道Spring是如何開啟事務的嗎?其實,當我們使用@Transactional注解時,Spring會通過AOP(面向切面編程)在運行時創建代理對象,來管理事務的開啟和關閉。這個過程對我們來說是透明的,但了解其背后的機制對于深入理解Spring事務是很有幫助的。

事務回滾

默認情況下,如果被@Transactional注解的方法拋出了運行時異常(RuntimeException)或者Error,Spring就會回滾事務。但是,如果你想讓事務在遇到非運行時異常時也回滾,可以這樣做:

@Transactional(rollbackFor = Exception.class)
public void createUserWithRollbackForException(String name) throws Exception {// ...
}

性能優化

事務雖好,但也不是沒有成本的。在某些高并發場景下,過多的事務操作可能會成為性能瓶頸。為了優化性能,我們可以通過以下幾種方式:

  1. 減少事務范圍:盡量讓事務只包含那些必須要在同一事務中完成的操作。
  2. 只讀事務:如果事務只涉及到數據的讀取,可以將事務標記為只讀,這樣可以幫助數據庫優化事務處理。
@Transactional(readOnly = true)
public User findUserById(Long id) {return userRepository.findById(id).orElse(null);
}

失效場景

在使用Spring事務的時候,有些情況可能會導致事務失效,比如:

  1. 自調用問題:在同一個類中,一個非事務方法調用事務方法,事務是不會起作用的。
  2. 異常處理:如果你在事務方法中捕獲了所有異常,并沒有重新拋出,事務是不會回滾的。

使用場景

事務通常用在需要保證一系列操作要么全部成功,要么全部失敗的場景,比如:

  • 用戶注冊時,需要同時創建用戶記錄和用戶的初始數據。
  • 訂單支付時,需要更新訂單狀態和用戶的賬戶余額。

代碼示例

讓我們再看一個例子,模擬用戶轉賬的場景:

@Transactional
public void transfer(Long fromId, Long toId, BigDecimal amount) {User fromUser = userRepository.findById(fromId).orElseThrow();User toUser = userRepository.findById(toId).orElseThrow();fromUser.setBalance(fromUser.getBalance().subtract(amount));toUser.setBalance(toUser.getBalance().add(amount));userRepository.save(fromUser);userRepository.save(toUser);
}

在這個例子中,我們通過事務確保了轉賬操作的原子性。如果在轉賬過程中發生任何異常,比如余額不足,整個操作都會回滾,保證賬戶的數據一致性。

SpringBoot中事務管理的一些更高級和具體的應用場景

示例1:聲明式事務的傳播行為

Spring事務的傳播行為定義了事務方法之間的交互方式。舉個例子,我們來看REQUIREDREQUIRES_NEW傳播行為的區別。

@Service
public class AccountService {@Autowiredprivate TransferService transferService;@Transactional(propagation = Propagation.REQUIRED)public void methodA() {// 這里的操作在methodA的事務范圍內transferService.methodB();// 如果methodB出錯,整個methodA都會回滾}@Transactional(propagation = Propagation.REQUIRES_NEW)public void methodB() {// 這里的操作有自己的獨立事務// 即使methodA失敗了,methodB的操作還是會提交}
}

示例2:編程式事務管理

除了聲明式事務,Spring還支持編程式事務管理,這在某些復雜的場景下非常有用。

@Service
public class ComplexService {@Autowiredprivate TransactionTemplate transactionTemplate;public void executeComplexLogic() {transactionTemplate.execute(new TransactionCallback<Void>() {@Overridepublic Void doInTransaction(TransactionStatus status) {// 這里是你的業務邏輯// 如果需要回滾,可以調用 status.setRollbackOnly();return null;}});}
}

示例3:事務的隔離級別

事務的隔離級別決定了一個事務可能受其他并發事務影響的程度。比如,我們來看看如何設置隔離級別:

@Transactional(isolation = Isolation.SERIALIZABLE)
public void transferMoney(Long fromAccountId, Long toAccountId, BigDecimal amount) {// 這個方法會以最高的隔離級別運行,以避免并發事務帶來的問題// 但是性能可能會受影響
}

示例4:事務超時設置

在某些長時間運行的事務中,你可能需要設置事務的超時時間,以避免長時間占用資源。

@Transactional(timeout = 10) // 10秒超時
public void processLargeData() {// 這個方法如果運行超過10秒,事務會被標記為回滾
}

示例5:事務回滾的條件自定義

有時候,你可能需要自定義事務回滾的條件。比如,只在特定的異常出現時才回滾。

@Transactional(rollbackFor = {CustomException.class})
public void updateUserDetails(User user) throws CustomException {// 這個方法只在CustomException拋出時才回滾// 其他異常不會觸發回滾
}

示例6:嵌套事務

嵌套事務允許在一個事務內部開始一個新的事務。如果內部事務失敗,它會回滾到它開始的狀態,而不影響外部事務。

@Transactional
public void parentMethod() {// 父事務的操作...try {nestedMethod();} catch (Exception e) {// 處理內部事務異常,父事務可以繼續}// 父事務的其他操作...
}@Transactional(propagation = Propagation.NESTED)
public void nestedMethod() {// 嵌套事務的操作...
}

示例7:聲明式事務與異常處理

處理聲明式事務時,異常的處理方式至關重要。下面是一個常見的錯誤處理方式。

@Transactional
public void updateUser() {try {// 更新用戶數據的操作...} catch (Exception e) {// 捕獲異常,這將導致事務不回滾}
}

在這個例子中,由于異常被捕獲并沒有重新拋出,事務將不會回滾,這可能會導致數據的不一致性。

示例8:使用事務同步管理器

在某些情況下,你可能需要直接與事務同步管理器進行交互,以獲取當前事務的狀態信息。

public void complexBusinessLogic() {boolean isCurrentTransactionActive = TransactionSynchronizationManager.isActualTransactionActive();if (isCurrentTransactionActive) {// 執行依賴于當前事務的操作...}
}

示例9:異步方法與事務

異步方法和事務一起使用時需要特別小心,因為異步方法通常會在不同的線程中運行,這可能會導致事務管理出現問題。

@Async
@Transactional
public Future<String> asyncMethodWithTransaction() {// 異步操作,但事務可能不會按預期工作// 因為它可能在不同的線程中執行return new AsyncResult<>("Done");
}

示例10:事務日志記錄

在某些業務場景中,你可能需要記錄事務的執行情況,特別是在事務提交或回滾時。

@Transactional
public void transactionalMethodWithLogging() {// 事務操作...TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {@Overridepublic void afterCommit() {// 記錄事務提交后的日志}@Overridepublic void afterCompletion(int status) {if (status == TransactionSynchronization.STATUS_ROLLED_BACK) {// 記錄事務回滾的日志}}});
}

通過這些示例,你可以看到Spring事務管理在不同場景下的應用。

理解這些復雜場景對于能夠在實際開發中靈活運用Spring事務管理至關重要。

記住,每個場景都有其特殊性,選擇正確的事務策略可以幫助你避免許多常見的問題。

核心要點

  1. 基本使用:使用@Transactional注解來聲明事務,這是Spring提供的一種聲明式事務管理方式。
  2. 事務傳播行為:Spring事務的傳播行為定義了事務之間的相互作用,如REQUIRED,?REQUIRES_NEW,?NESTED等,這決定了事務是否共享或獨立。
  3. 事務的隔離級別:隔離級別(如READ_COMMITTED,?SERIALIZABLE等)控制事務之間的可見性,防止諸如臟讀、不可重復讀、幻讀等問題。
  4. 事務的回滾規則:默認情況下,Spring僅在運行時異常發生時回滾事務。可通過rollbackFor自定義回滾條件。
  5. 超時和只讀設置:可以設置事務的超時時間和聲明只讀事務,以優化性能和資源利用。

高級應用場景

  1. 編程式事務管理:通過TransactionTemplate或直接使用PlatformTransactionManager來手動管理事務。
  2. 嵌套事務:通過NESTED傳播行為實現嵌套事務,內部事務失敗不影響外部事務。
  3. 異步和事務:異步方法中使用事務需要特別注意,由于執行線程的不同,可能影響事務的管理。
  4. 事務同步管理:使用TransactionSynchronizationManager進行事務的細粒度控制,如在事務提交或回滾后執行特定操作。
  5. 異常處理與事務回滾:異常處理在事務中非常重要,不當的異常處理可能導致事務不回滾,引起數據不一致。

實際應用建議

  • 合理設計事務范圍:避免將大量操作包含在單一事務中,以減少資源鎖定時間和提高性能。
  • 注意異常處理:確保適當的異常拋出,以觸發事務回滾。
  • 避免在異步方法中使用事務:或者確保你理解如何在多線程環境下正確管理事務。
  • 謹慎使用嵌套事務:它們可能會增加復雜性和性能開銷。
  • 監控和調優:在生產環境中監控事務的性能,根據需要調整事務策略和配置。

總之,SpringBoot中的事務管理是一個強大但需要謹慎使用的工具。

理解它的工作原理和應用場景,可以幫助你更有效地管理數據一致性和應用性能。

記住,每個應用的需求不同,所以在使用事務時,總是要考慮到你的具體場景和需求。

最后說一句(求關注,求贊,別白嫖我)

最近無意間獲得一份阿里大佬寫的刷題筆記,一下子打通了我的任督二脈,進大廠原來沒那么難。

這是大佬寫的, 7701頁的BAT大佬寫的刷題筆記,讓我offer拿到手軟

項目文檔&視頻:

項目文檔 & 視頻

本文,已收錄于,我的技術網站 ddkk.com,有大廠完整面經,工作技術,架構師成長之路,等經驗分享

求一鍵三連:點贊、分享、收藏

點贊對我真的非常重要!在線求贊,加個關注我會非常感激

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

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

相關文章

【金融數據分析】計算滬深300指數行業權重分布并用餅圖展示

前言 前面的文章我們已經介紹了如何獲取滬深300成分股所述行業以及權重的數據&#xff0c;想要了解這部分內容的小伙伴可以閱讀上一篇文章 springbootjdbcTemplatesqlite編程示例——以滬深300成分股數據處理為例-CSDN博客 那么有了上文獲取的數據&#xff0c;我們實際上可以…

【rabbitMQ】rabbitMQ控制臺模擬收發消息

目錄 1.新建隊列 2.交換機綁定隊列 3.查看消息是否到達隊列 總結&#xff1a; 1.新建隊列 2.交換機綁定隊列 點擊amq.fonout 3.查看消息是否到達隊列 總結&#xff1a; 生產者&#xff08;publisher&#xff09;發送消息&#xff0c;先到達交換機&#xff0c;再到隊列&…

微信小程序uni-app:常用Form表單組件使用示例

目錄 input 輸入框picker 選擇器 input 輸入框 https://developers.weixin.qq.com/miniprogram/dev/component/input.htmlhttps://uniapp.dcloud.net.cn/component/input.html <inputclass"input-class"type"text"v-model"value"placeholde…

Linux下文本三劍客:grep、awk、sed之對比

一、grep 主要用于搜索某些字符串&#xff1b;sed、awk 用于處理文本&#xff1a; grep基本是以行為單位處理文本的&#xff1b; 而awk可以做更細分的處理&#xff0c;通過指定分隔符將一行&#xff08;一條記錄&#xff09;劃分為多個字段&#xff0c;以字段為單位處理文本。…

python輸出菱形字符圖案 附實戰代碼

下面是一個Python程序&#xff0c;可以用來輸出菱形字符圖案。這個程序使用了兩個嵌套的for循環&#xff0c;以及字符串連接操作。 # 獲取用戶輸入 n int(input("請輸入菱形的邊長&#xff1a;"))# 生成上半部分菱形 for i in range(1, n 1, 2):print(" &quo…

SDK,但未在應用內的隱私政策/在AppGallery Connect上提交的隱私政策內容中進行明示,不符合華為應用市場審核標準。

&#xff08;暫時用不到的也建議收藏一下&#xff0c;因為文章持續更新中&#xff09; 最新更改時間&#xff1a;20023-12-10 第三方SDK合集列表 為了確保用戶個人信息的安全&#xff0c;我們對使用到的第三方提供的軟件開發包&#xff08;SDK&#xff09;進行了嚴格的安全檢…

期末速成數據庫極簡版【存儲過程】(5)

目錄 【7】系統存儲過程 【8】用戶存儲過程——帶輸出參數的存儲過程 創建存儲過程 存儲過程調用 【9】用戶存儲過程——不帶輸出參數的存儲過程 【7】系統存儲過程 系統存儲我們就不做過程講解用戶存儲過程會考察一道大題&#xff0c;所以我們把重點放在用戶存儲過程。…

vscode 編寫爬蟲爬取王者榮耀壁紙

網上關于爬蟲大部分教程和編輯器用的都不是vscode &#xff0c;此教程用到了vscode、Python、bs4、requests。 vscode配置Python安裝環境可以看看這個大佬的教程 03-vscode安裝和配置_嗶哩嗶哩_bilibili vscode配置爬蟲環境可以參考這個大佬的教程【用Vscode實現簡單的python…

U4_1 語法分析之自頂向下分析

文章目錄 一、定義1、任務2、對比3、方法4、自頂向下面臨問題 二、自頂向下分析1、概念2、特點3、二義性問題4、左遞歸問題1&#xff09;概念2&#xff09;消除3&#xff09;間接左遞歸 5、回溯問題1&#xff09;概念2&#xff09;消除3&#xff09;解決方法 6、總結 三、遞歸子…

Java 線程池中 submit() 和 execute() 方法有什么區別?

Java 線程池中 submit() 和 execute() 方法有什么區別&#xff1f; 在 Java 中&#xff0c;ExecutorService 接口是用于管理和執行線程的框架&#xff0c;它定義了兩個用于提交任務的方法&#xff1a;submit() 和 execute()。這兩種方法有一些區別&#xff1a; 返回值&#xf…

【Proteus仿真】【51單片機】光照強度檢測系統

文章目錄 一、功能簡介二、軟件設計三、實驗現象聯系作者 一、功能簡介 本項目使用Proteus8仿真51單片機控制器&#xff0c;使共陰數碼管&#xff0c;PCF8591 ADC模塊、光敏傳感器等。 主要功能&#xff1a; 系統運行后&#xff0c;數碼管顯示光傳感器采集光照強度值&#xff…

Gitzip插件【Github免翻下載】

今天給大家推薦一個github下載的插件&#xff0c;平常大家下載應該無外乎就是以下兩種&#xff1a; Download zip利用git clone 但是這兩種各有各的弊端&#xff0c;前者一般需要科學上網才可以&#xff0c;后者下載不穩定經常中途斷掉。 今天給推薦一個款瀏覽器插件-Gitzip.大…

基于SSM的java衣服商城

基于SSM的java衣服商城 一、系統介紹二、功能展示四、其他系統實現五、獲取源碼 一、系統介紹 項目類型&#xff1a;Java EE項目 項目名稱&#xff1a;基于SSM的美衣商城 項目架構&#xff1a;B/S架構 開發語言&#xff1a;Java語言 前端技術&#xff1a;Layui等 后端技術…

Flask和Vue框架實現WebSocket消息通信

1 安裝環境 1.1 安裝Flask環境 主要的安裝包 Flask、Flask-SocketIO&#xff0c;注意Python版本要求3.6 # Flask-SocketIO參考地址 https://flask-socketio.readthedocs.io/en/latest/ https://github.com/miguelgrinberg/flask-socketio更新基礎環境 # 更新pip python -m …

Unity發布WebGL測試界面處理方式參考

如果使用Unity發布WebGL經常會和網頁進行交互&#xff0c;為了能夠做到界面統一&#xff0c;往往所有UI都是在頁面上開發的&#xff0c;Unity本身不做任何UI或者只做三維UI&#xff0c;但是在開發過程中&#xff0c;為了測試接口&#xff0c;難免要在Unity中做一些UI來方便測試…

以太坊虛擬機EVM介紹,智能合約詳解

以太坊為例&#xff1a;什么是智能合約&#xff1f;智能合約怎么部署、調用、執行&#xff1f;智能合約的原理&#xff1f;智能合約存在哪兒&#xff1f;如何區分調用的是智能合約&#xff1f;世界狀態數據庫、EVM、智能合約它們之間的關系&#xff1f; 什么是智能合約 指的是…

【Hive】啟動beeline連接hive報錯解決

1、解決報錯2、在datagrip上連接hive 1、解決報錯 剛開始一直報錯&#xff1a;啟動不起來 hive-site.xml需要配置hiveserver2相關的 在hive-site.xml文件中添加如下配置信息 <!-- 指定hiveserver2連接的host --> <property><name>hive.server2.thrift.bin…

機器人與3D視覺 Robotics Toolbox Python 二 空間位姿描述

空間位姿描述 二維空間位姿描述 二維空間位姿表示方法 from spatialmath.base import * from spatialmath import * T1 SE2(x3,y3,theta30,unit"deg") trplot2(T1.A,frame"T1",dims[0, 5, 0, 5]) T2transl2(3, 4) trplot2(T2,frame"T2",dims…

如何理解 RPC 遠程服務調用?

本文主要講解 RPC 遠程服務調用相關的知識。 RPC 遠程服務調用是分布式服務架構的基礎&#xff0c;無論微服務設計上層如何發展&#xff0c;討論服務治理都繞不開遠程服務調用&#xff0c;那么如何理解 RPC、有哪些常見的 RPC 框架、實現一款 RPC 框架需要哪些技術呢&#xff…

解決electron修改主進程后需要重啟才生效

nodemon 是一種工具&#xff0c;可在檢測到目錄中的文件更改時通過自動重新啟動節點應用程序來幫助開發基于 node.js 的應用程序 nodemon 特性 自動重新啟動應用程序。檢測要監視的默認文件擴展名。默認支持 node&#xff0c;但易于運行任何可執行文件&#xff0c;如 python、…