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

Java?Spring事務(wù)管理超詳細指南

 更新時間:2026年01月14日 10:14:32   作者:無名-CODING  
Spring的事務(wù)管理提供了聲明式事務(wù)管理,支持聲明式事務(wù)的控制,簡化了事務(wù)管理的復(fù)雜性,下面這篇文章主要介紹了Java?Spring事務(wù)管理的相關(guān)資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下

一、 引言:為什么我們需要事務(wù)?

1.1 一個經(jīng)典的轉(zhuǎn)賬場景

想象一下,你正在使用手機銀行給朋友轉(zhuǎn)賬 100 塊錢。這個動作在代碼層面通常分為兩步:

  1. 你的賬戶扣款 100 元 (UPDATE account SET balance = balance - 100 WHERE id = A)
  2. 朋友的賬戶增加 100 元 (UPDATE account SET balance = balance + 100 WHERE id = B)

如果發(fā)生了意外會怎樣?

  • 假如第一步執(zhí)行成功了,你的錢扣了。
  • 緊接著,程序報錯了(比如斷網(wǎng)了、數(shù)據(jù)庫崩了、或者代碼拋異常了)。
  • 結(jié)果:你的錢沒了,朋友也沒收到錢!?? 這就是嚴重的數(shù)據(jù)不一致問題。

1.2 事務(wù)的作用

為了解決這個問題,數(shù)據(jù)庫引入了 事務(wù)(Transaction) 的概念。
事務(wù)就是把一組數(shù)據(jù)庫操作看作一個整體。這個整體內(nèi)的操作,要么全部成功,要么全部失敗(回滾),不允許出現(xiàn) “做一半” 的情況。

二、 事務(wù)的四大特性(ACID)

這是面試必考題!理解這四個詞,就理解了事務(wù)的靈魂。

特性英文解釋通俗理解
原子性Atomicity事務(wù)是不可分割的最小單位,要么全做,要么全不做。要么大家都成功,要么大家一起"死"(回滾),不能有幸存者。
一致性Consistency事務(wù)執(zhí)行前后,數(shù)據(jù)必須保持合規(guī)的邏輯狀態(tài)。轉(zhuǎn)賬前 A+B=200,轉(zhuǎn)賬后 A+B 還是 200,錢不會憑空消失或變多。
隔離性Isolation多個事務(wù)并發(fā)執(zhí)行時,互不干擾。我在操作這條數(shù)據(jù)時,你別來搗亂(具體看隔離級別)。
持久性Durability事務(wù)一旦提交,修改就是永久的,即使系統(tǒng)崩潰也不丟失。落子無悔,寫進硬盤了,斷電也沒事。

三、 Spring 中的事務(wù)管理

在 Java 開發(fā)中,我們幾乎都在使用 Spring 框架來管理事務(wù)。Spring 提供了兩種方式:

  1. 編程式事務(wù):在代碼里手動寫 commit(), rollback()(代碼侵入性太強,現(xiàn)在很少用了)。
  2. 聲明式事務(wù):使用注解 @Transactional,把繁瑣的事務(wù)邏輯交給 Spring 代理處理(推薦,最常用)。

3.1 快速入門代碼示例

下面是一個典型的 Service 層代碼,演示了如何使用 @Transactional。

package com.example.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.example.mapper.AccountMapper;

@Service
public class AccountService {

    @Autowired
    private AccountMapper accountMapper;

    /**
     * 轉(zhuǎn)賬方法
     * 
     * @Transactional 注解說明:
     * 1. 這是一個事務(wù)方法。
     * 2. Spring 會自動在方法開始前開啟事務(wù)(Begin)。
     * 3. 如果方法正常執(zhí)行結(jié)束,Spring 自動提交事務(wù)(Commit)。
     * 4. 如果方法拋出了 RuntimeException (運行時異常),Spring 自動回滾事務(wù)(Rollback)。
     */
    @Transactional(rollbackFor = Exception.class) // 建議:顯式指定遇到任何異常都回滾
    public void transfer(Long fromId, Long toId, Double amount) {
        
        // 1. 扣錢 (可能發(fā)生異常的地方)
        accountMapper.decreaseBalance(fromId, amount);
        System.out.println("用戶 " + fromId + " 扣款成功");

        // 模擬一個意外異常:例如除以零,或者空指針
        // int i = 1 / 0; 
        // 如果上面這行解開注釋,整個事務(wù)會回滾,第一步扣的錢會加回去。

        // 2. 加錢
        accountMapper.increaseBalance(toId, amount);
        System.out.println("用戶 " + toId + " 入賬成功");
        
        // 方法結(jié)束 -> 提交事務(wù)
    }
}

四、 核心難點:事務(wù)的傳播行為 (Propagation)

“傳播行為” 是 Spring 特有的概念,解決的是 Service 方法互相調(diào)用 時,事務(wù)該怎么算的問題。
比如:方法 A 調(diào)用了 方法 B,由于 A 和 B 上都有 @Transactional 注解,那 B 是加入 A 的事務(wù)?還是自己新開一個?

Spring 定義了 7 種傳播行為,最常用的有下面 3 種:

1. REQUIRED (默認值)

?? 口語解釋:“有就加入,沒有就新建。”

  • 場景:如果不指定,默認就是這個。
  • 行為
    • 如果 A 已經(jīng)開啟了事務(wù),B 就加入 A 的事務(wù)(它倆是同一條船上的螞蚱,要么一起成功,要么一起回滾)。
    • 如果 A 沒有事務(wù),B 就自己開啟一個新的事務(wù)。

2. REQUIRES_NEW

?? 口語解釋:“不管你有沒有,我都自己玩。”

  • 場景:記錄日志操作。不管業(yè)務(wù)邏輯成功還是失敗,日志都必須記錄下來,不能因為業(yè)務(wù)回滾了日志也就沒了。
  • 行為
    • B 方法會掛起 A 的事務(wù),自己開啟一個全新的事務(wù)。
    • B 的成功失敗,不影響 A;A 的回滾,也不影響 B(前提是 B 已經(jīng)提交了)。
    • 代碼示例
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void logOperation() {
        // 這里的操作在一個完全獨立的事務(wù)中
        logMapper.insertLog("操作發(fā)生");
    }
    

3. NESTED (嵌套事務(wù))

?? 口語解釋:“你是父,我是子。你掛我也掛,我掛你不一定掛。”

  • 行為
    • 基于數(shù)據(jù)庫的 Savepoint(保存點)技術(shù)。
    • B 是 A 的一個子事務(wù)。如果 A 回滾,B 一定回滾。
    • 但是如果 B 異?;貪L了,A 可以選擇捕獲異常,繼續(xù)執(zhí)行其他邏輯,不一定要回滾。

五、 核心難點:事務(wù)的隔離級別 (Isolation)

當(dāng)很多用戶同時操作數(shù)據(jù)庫時(高并發(fā)),會產(chǎn)生一些奇怪的現(xiàn)象。通過設(shè)置隔離級別來權(quán)衡數(shù)據(jù)的準確性和性能。

5.1 并發(fā)可能導(dǎo)致的問題

  1. 臟讀 (Dirty Read):讀到了別人還沒提交的數(shù)據(jù)。(最嚴重,絕對不允許)
    • 例子:A 沒提交轉(zhuǎn)賬,B 讀到了錢多了,結(jié)果 A 回滾了,B 讀到的是假數(shù)據(jù)。
  2. 不可重復(fù)讀 (Non-repeatable Read):在一個事務(wù)里,兩次讀取同一行數(shù)據(jù),結(jié)果不一樣(因為中間被別人改了)。
    • 例子:我看庫存是 1,準備買,中間被別人買走了,我再看庫存變成 0 了。
  3. 幻讀 (Phantom Read):在一個事務(wù)里,兩次查詢通過同樣的條件,結(jié)果條數(shù)不一樣(因為中間別人插入/刪除了數(shù)據(jù))。

5.2 SQL 標(biāo)準的四個隔離級別

級別名稱解決的問題性能
READ_UNCOMMITTED讀未提交啥也沒解決,可能臟讀最高(極不安全)
READ_COMMITTED讀已提交解決了臟讀 (Oracle/SQLServer 默認)較好
REPEATABLE_READ可重復(fù)讀解決了臟讀不可重復(fù)讀 (MySQL 默認)一般
SERIALIZABLE串行化解決了所有問題 (完全排隊執(zhí)行)最差(像單線程)

?? Spring 配置方式
@Transactional(isolation = Isolation.REPEATABLE_READ)

六、 常見坑點:為什么我的 @Transactional 失效了?

這是新手最容易遇到的問題,代碼寫了注解,但異常拋出時數(shù)據(jù)居然沒有回滾!常見原因如下:

  1. 方法不是 public 的:Spring 默認只代理 public 方法。
  2. 同類內(nèi)部調(diào)用
    • 錯誤示范:方法 A 調(diào) 方法 B,A 沒有注解,B 有注解。在 Controller 調(diào) A 時,B 的事務(wù)不會生效。
    • 原因:Spring 事務(wù)是基于 AOP 代理 的,同類內(nèi)部調(diào)用 this.methodB() 是直接調(diào)用原始對象的方法,繞過了 Spring 的代理對象,所以事務(wù)沒開啟。
  3. 異常被你自己 catch 吃了
    • 錯誤示范:
      @Transactional
      public void method() {
          try {
              // 業(yè)務(wù)代碼
          } catch (Exception e) {
              e.printStackTrace(); 
              // ? 錯誤!這里把異常捕獲了,Spring 以為代碼執(zhí)行正常,就會提交事務(wù)!
          }
      }
      
    • 修正:在 catch 塊里 throw new RuntimeException(e) 或者手動回滾 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();。
  4. 數(shù)據(jù)庫引擎不支持:例如 MySQL 的 MyISAM 引擎是不支持事務(wù)的,必須用 InnoDB。

七、 高頻面試題 QA

Q1:Spring 事務(wù)默認回滾什么異常?

A:默認只回滾 RuntimeException(運行時異常)和 Error。對于 Exception(受檢異常,如 IOException),默認是不回滾的。
追問:怎么讓受檢異常也回滾?
A:配置 @Transactional(rollbackFor = Exception.class)。

Q2:REQUIRED 和 REQUIRES_NEW 的區(qū)別?

A

  • REQUIRED:如果當(dāng)前有事務(wù),就加入;如果沒有,就新建。多個方法共用一個物理事務(wù),一起提交或回滾。
  • REQUIRES_NEW:無論當(dāng)前有沒有事務(wù),都掛起當(dāng)前事務(wù),自己開啟一個新事務(wù)。兩個事務(wù)互不影響,是隔離的。

Q3:什么是 Spring 的事務(wù)失效?舉個例子。

A:最經(jīng)典的就是自調(diào)用問題。在同一個 Service 類中,非事務(wù)方法 A 調(diào)用事務(wù)方法 B,導(dǎo)致 B 的事務(wù)失效。因為 Spring AOP 生成代理對象時,只有通過代理對象調(diào)用方法才能攔截事務(wù),內(nèi)部 this 調(diào)用直接走了目標(biāo)對象。

Q4:ACID 是靠什么保證的?(進階)

A

  • A (原子性):靠 undo log (回滾日志) 保證,失敗了可以回滾。
  • C (一致性):是最終目的,靠代碼邏輯和 AID 共同保證。
  • I (隔離性):靠 MVCC (多版本并發(fā)控制) 和 機制保證。
  • D (持久性):靠 redo log (重做日志) 保證,斷電也能恢復(fù)。

八、 總結(jié)

事務(wù)管理是后端開發(fā)的"安全帶"。雖然 Spring Boot 讓我們使用 @Transactional 一個注解就能搞定事務(wù),但作為開發(fā)者,我們必須深入理解其背后的傳播機制隔離級別,才能在復(fù)雜的業(yè)務(wù)場景下寫出健壯的代碼。

到此這篇關(guān)于Java Spring事務(wù)管理的文章就介紹到這了,更多相關(guān)Java Spring事務(wù)管理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java實現(xiàn)Excel批量導(dǎo)入數(shù)據(jù)

    Java實現(xiàn)Excel批量導(dǎo)入數(shù)據(jù)

    這篇文章主要為大家詳細介紹了Java實現(xiàn)Excel批量導(dǎo)入數(shù)據(jù),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-08-08
  • SpringBoot整合DeepSeek技術(shù)指南(實際應(yīng)用場景)

    SpringBoot整合DeepSeek技術(shù)指南(實際應(yīng)用場景)

    這篇文章主要介紹了SpringBoot整合DeepSeek技術(shù)指南,本文通過實際應(yīng)用場景模擬給大家介紹的非常詳細,感興趣的朋友一起看看吧
    2025-04-04
  • 一個Servlet是如何處理多個請求的?

    一個Servlet是如何處理多個請求的?

    以前我一直以為一個Servlet只能處理一個請求,后來發(fā)現(xiàn)是自己太菜了,可以借助攜帶一個參數(shù)來完成多個請求的處理,根據(jù)參數(shù)的不同,在核心的service方法中調(diào)用不同的業(yè)務(wù)方法,來實現(xiàn)處理多個servlet請求的目的,廢話不多說,直接上代碼,需要的朋友可以參考下
    2021-06-06
  • mybatis多層嵌套resultMap及返回自定義參數(shù)詳解

    mybatis多層嵌套resultMap及返回自定義參數(shù)詳解

    這篇文章主要介紹了mybatis多層嵌套resultMap及返回自定義參數(shù)詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • SpringBoot淺析安全管理之Spring Security配置

    SpringBoot淺析安全管理之Spring Security配置

    安全管理是軟件系統(tǒng)必不可少的的功能。根據(jù)經(jīng)典的“墨菲定律”——凡是可能,總會發(fā)生。如果系統(tǒng)存在安全隱患,最終必然會出現(xiàn)問題,這篇文章主要介紹了SpringBoot安全管理Spring Security基本配置
    2022-08-08
  • Java服務(wù)端服務(wù)監(jiān)控:Prometheus與Spring Boot Actuator的集成方式

    Java服務(wù)端服務(wù)監(jiān)控:Prometheus與Spring Boot Actuator的集成方式

    本文介紹了如何將Prometheus與SpringBootActuator集成,實現(xiàn)對Java服務(wù)端應(yīng)用的監(jiān)控,通過集成,可以利用Prometheus的強大監(jiān)控能力,及時發(fā)現(xiàn)和解決性能問題
    2024-12-12
  • SpringCloud Ribbon負載均衡代碼實例

    SpringCloud Ribbon負載均衡代碼實例

    這篇文章主要介紹了SpringCloud Ribbon負載均衡代碼實例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-03-03
  • SpringBoot中配置雙數(shù)據(jù)源的實現(xiàn)示例

    SpringBoot中配置雙數(shù)據(jù)源的實現(xiàn)示例

    在許多應(yīng)用程序中,可能會遇到需要連接多個數(shù)據(jù)庫的情況,本文主要介紹了SpringBoot中配置雙數(shù)據(jù)源的實現(xiàn)示例,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-08-08
  • Java?Mybatis框架由淺入深全解析下篇

    Java?Mybatis框架由淺入深全解析下篇

    MyBatis是一個優(yōu)秀的持久層框架,它對jdbc的操作數(shù)據(jù)庫的過程進行封裝,使開發(fā)者只需要關(guān)注SQL本身,而不需要花費精力去處理例如注冊驅(qū)動、創(chuàng)建connection、創(chuàng)建statement、手動設(shè)置參數(shù)、結(jié)果集檢索等jdbc繁雜的過程代碼,本文將作為最終篇為大家介紹MyBatis的使用
    2022-07-07
  • 怎么在AVD上安裝apk軟件

    怎么在AVD上安裝apk軟件

    執(zhí)行 Windows 開始菜單 => 所有程序 => 附件 => 命令提示符 或通過 Win+R 組合鍵調(diào)出 運行 對話框輸入cmd 單擊確定即可
    2013-09-09

最新評論

哈密市| 德庆县| 昌宁县| 和硕县| 前郭尔| 崇仁县| 环江| 汾西县| 紫云| 眉山市| 舞阳县| 商水县| 三台县| 沅江市| 搜索| 岳阳县| 天气| 新田县| 保定市| 博白县| 安溪县| 鹿泉市| 卢氏县| 贵南县| 吴江市| 温泉县| 绍兴市| 伊通| 青田县| 泾川县| 辽宁省| 河池市| 平凉市| 赤城县| 宿州市| 永靖县| 潞城市| 马关县| 特克斯县| 麻栗坡县| 精河县|