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

SpringBoot 事務(wù)深度解析之從理論到實踐的完整指南

 更新時間:2026年03月03日 09:51:09   作者:CodeSuc  
本文詳細介紹了SpringBoot事務(wù)的基礎(chǔ)理論、核心機制、使用詳解和常見問題與解決方案,從事務(wù)的定義及ACID特性開始,逐步深入Spring事務(wù)的實現(xiàn)機制,感興趣的朋友跟隨小編一起看看吧

前言

在后端開發(fā)中,數(shù)據(jù)一致性是衡量系統(tǒng)可靠性的核心指標之一,而事務(wù)正是保障數(shù)據(jù)一致性的關(guān)鍵技術(shù)。無論是電商系統(tǒng)的訂單支付、金融平臺的資金流轉(zhuǎn),還是企業(yè)級應(yīng)用的業(yè)務(wù)數(shù)據(jù)處理,都離不開事務(wù)的保駕護航。SpringBoot作為當(dāng)前最流行的Java開發(fā)框架,其對事務(wù)的支持簡潔高效,極大降低了開發(fā)者的使用成本。本文將從事務(wù)的基礎(chǔ)理論出發(fā),逐步深入SpringBoot事務(wù)的實現(xiàn)機制、使用方式、常見問題及優(yōu)化方案,幫助開發(fā)者全面掌握SpringBoot事務(wù)知識,輕松應(yīng)對實際開發(fā)中的數(shù)據(jù)一致性挑戰(zhàn)。

第一章 事務(wù)基礎(chǔ):你必須掌握的核心概念

1.1 什么是事務(wù)?

事務(wù)(Transaction)是數(shù)據(jù)庫操作的基本單元,它是由一組不可分割的數(shù)據(jù)庫操作組成的邏輯集合。這組操作要么全部執(zhí)行成功,要么全部執(zhí)行失敗,不存在部分執(zhí)行的中間狀態(tài)。例如,在電商下單場景中,需要完成“扣減庫存”“創(chuàng)建訂單”“扣減余額”三個操作,這三個操作就構(gòu)成一個事務(wù)。如果其中任意一個操作失敗,為了保證數(shù)據(jù)一致性,其他已執(zhí)行的操作必須回滾,恢復(fù)到操作前的狀態(tài)。

事務(wù)本質(zhì)上是數(shù)據(jù)庫提供的一種機制,主流的關(guān)系型數(shù)據(jù)庫如MySQL、Oracle、PostgreSQL等都原生支持事務(wù)。而SpringBoot則是在數(shù)據(jù)庫事務(wù)的基礎(chǔ)上,通過Spring框架的封裝,為開發(fā)者提供了更便捷、更靈活的事務(wù)管理能力。

1.2 事務(wù)的ACID特性

ACID是事務(wù)的四大核心特性,是衡量事務(wù)機制是否可靠的標準,也是理解事務(wù)本質(zhì)的關(guān)鍵。這四個特性相互關(guān)聯(lián),共同保障數(shù)據(jù)的一致性。

1.2.1 原子性(Atomicity)

原子性是指事務(wù)中的所有操作是一個不可分割的整體,如同“原子”一樣不可再分。事務(wù)的原子性要求:要么事務(wù)中的所有操作都執(zhí)行成功并提交,要么所有操作都執(zhí)行失敗并回滾,不存在“部分成功、部分失敗”的情況。

例如,銀行轉(zhuǎn)賬業(yè)務(wù)中,“從A賬戶扣減1000元”和“向B賬戶增加1000元”是一個事務(wù)的兩個操作。如果扣減操作成功但增加操作失敗,原子性會保證扣減的1000元回滾到A賬戶,避免出現(xiàn)A賬戶資金減少但B賬戶資金未增加的錯誤數(shù)據(jù)。

1.2.2 一致性(Consistency)

一致性是指事務(wù)執(zhí)行前后,數(shù)據(jù)庫中的數(shù)據(jù)必須處于一個合法、一致的狀態(tài),即數(shù)據(jù)需要滿足業(yè)務(wù)規(guī)則和完整性約束。一致性是事務(wù)的最終目標,其他三個特性都是為了保障一致性而存在的。

以電商庫存管理為例,假設(shè)某商品的初始庫存為100件。如果同時有兩個訂單分別購買10件和20件商品,那么兩個事務(wù)執(zhí)行完成后,庫存應(yīng)該變?yōu)?0件,這就是數(shù)據(jù)的一致性。如果由于事務(wù)機制缺陷,導(dǎo)致最終庫存為80件或90件,就破壞了數(shù)據(jù)的一致性。

1.2.3 隔離性(Isolation)

隔離性是指多個事務(wù)同時并發(fā)執(zhí)行時,一個事務(wù)的執(zhí)行過程不會被其他事務(wù)干擾,各個事務(wù)之間相互隔離,如同在獨立的環(huán)境中執(zhí)行一樣。如果事務(wù)之間沒有隔離性,多個并發(fā)事務(wù)操作同一批數(shù)據(jù)時,可能會出現(xiàn)臟讀、不可重復(fù)讀、幻讀等問題,從而破壞數(shù)據(jù)一致性。

例如,事務(wù)A正在修改用戶的余額,此時事務(wù)B讀取該用戶的余額。如果沒有隔離性,事務(wù)B可能會讀取到事務(wù)A修改過程中的中間數(shù)據(jù),而這個數(shù)據(jù)最終可能因為事務(wù)A回滾而失效,導(dǎo)致事務(wù)B基于錯誤的數(shù)據(jù)進行業(yè)務(wù)處理。

1.2.4 持久性(Durability)

持久性是指事務(wù)一旦執(zhí)行成功并提交,其對數(shù)據(jù)庫中數(shù)據(jù)的修改就是永久性的,即使后續(xù)發(fā)生數(shù)據(jù)庫崩潰、服務(wù)器宕機等故障,已提交的事務(wù)數(shù)據(jù)也不會丟失。數(shù)據(jù)庫通常通過將事務(wù)日志寫入磁盤來實現(xiàn)持久性,當(dāng)系統(tǒng)故障恢復(fù)時,可以通過事務(wù)日志恢復(fù)已提交的事務(wù)數(shù)據(jù)。

例如,用戶完成訂單支付后,事務(wù)提交成功,此時即使數(shù)據(jù)庫服務(wù)器突然斷電,再次啟動后,用戶的支付記錄和訂單狀態(tài)也不會丟失,確保業(yè)務(wù)數(shù)據(jù)的可靠。

1.3 事務(wù)的并發(fā)問題

在多用戶并發(fā)訪問數(shù)據(jù)庫的場景下,如果事務(wù)的隔離性得不到保障,就會出現(xiàn)一系列并發(fā)問題。根據(jù)問題的嚴重程度,主要分為以下四類:

1.3.1 臟讀(Dirty Read)

臟讀是指一個事務(wù)讀取到了另一個事務(wù)尚未提交的修改數(shù)據(jù)。由于未提交的事務(wù)可能會回滾,因此讀取到的數(shù)據(jù)是“臟”的,即無效數(shù)據(jù)。

場景示例:事務(wù)A執(zhí)行“扣減用戶余額100元”操作,但未提交;此時事務(wù)B讀取該用戶的余額,得到扣減后的金額;隨后事務(wù)A因為異?;貪L,用戶余額恢復(fù)為原始值,但事務(wù)B已經(jīng)基于讀取到的臟數(shù)據(jù)進行了后續(xù)業(yè)務(wù)處理(如創(chuàng)建訂單),導(dǎo)致業(yè)務(wù)錯誤。

1.3.2 不可重復(fù)讀(Non-repeatable Read)

不可重復(fù)讀是指在同一個事務(wù)中,多次讀取同一批數(shù)據(jù)時,得到的結(jié)果不一致。這種問題通常是由于在兩次讀取之間,有其他事務(wù)修改并提交了該數(shù)據(jù)。

場景示例:事務(wù)A第一次讀取用戶余額為1000元;此時事務(wù)B修改該用戶余額為800元并提交;事務(wù)A再次讀取該用戶余額時,得到的結(jié)果變?yōu)?00元,與第一次讀取的結(jié)果不一致,導(dǎo)致事務(wù)A的業(yè)務(wù)邏輯出現(xiàn)混亂。

1.3.3 幻讀(Phantom Read)

幻讀是指在同一個事務(wù)中,多次執(zhí)行相同的查詢語句時,查詢結(jié)果的行數(shù)不一致。這種問題通常是由于在兩次查詢之間,有其他事務(wù)插入或刪除了符合查詢條件的數(shù)據(jù)。

場景示例:事務(wù)A執(zhí)行“查詢余額大于500元的用戶”操作,得到10條記錄;此時事務(wù)B插入了一條余額為600元的用戶數(shù)據(jù)并提交;事務(wù)A再次執(zhí)行相同的查詢語句,得到11條記錄,如同出現(xiàn)了“幻覺”一樣。

1.3.4 丟失修改(Lost Update)

丟失修改是指兩個事務(wù)同時修改同一數(shù)據(jù),后提交的事務(wù)會覆蓋先提交的事務(wù)的修改結(jié)果,導(dǎo)致先提交的事務(wù)的修改丟失。

場景示例:事務(wù)A讀取用戶余額為1000元,計劃修改為900元;同時事務(wù)B也讀取該用戶余額為1000元,計劃修改為800元;事務(wù)A先提交,將余額改為900元;隨后事務(wù)B提交,將余額改為800元,導(dǎo)致事務(wù)A的修改被丟失。

1.4 數(shù)據(jù)庫事務(wù)隔離級別

為了解決事務(wù)的并發(fā)問題,數(shù)據(jù)庫定義了不同的事務(wù)隔離級別。隔離級別越高,事務(wù)的并發(fā)問題越少,但數(shù)據(jù)庫的并發(fā)性能也會越低。開發(fā)者需要根據(jù)業(yè)務(wù)場景在數(shù)據(jù)一致性和并發(fā)性能之間進行權(quán)衡。SQL標準定義了四個隔離級別,不同的數(shù)據(jù)庫對這些隔離級別的支持程度有所不同。

1.4.1 讀未提交(Read Uncommitted)

最低的隔離級別,允許一個事務(wù)讀取另一個事務(wù)尚未提交的修改數(shù)據(jù)。該隔離級別無法解決臟讀、不可重復(fù)讀、幻讀等任何并發(fā)問題,實際開發(fā)中很少使用。

1.4.2 讀已提交(Read Committed)

允許一個事務(wù)讀取另一個事務(wù)已經(jīng)提交的修改數(shù)據(jù)。該隔離級別可以解決臟讀問題,但無法解決不可重復(fù)讀和幻讀問題。這是大多數(shù)數(shù)據(jù)庫的默認隔離級別,如Oracle、SQL Server等。

1.4.3 可重復(fù)讀(Repeatable Read)

保證同一個事務(wù)中,多次讀取同一批數(shù)據(jù)時,得到的結(jié)果一致。該隔離級別可以解決臟讀和不可重復(fù)讀問題,但無法完全解決幻讀問題(MySQL的InnoDB引擎通過MVCC機制在可重復(fù)讀級別下解決了幻讀問題)。這是MySQL的默認隔離級別。

1.4.4 串行化(Serializable)

最高的隔離級別,要求所有事務(wù)串行執(zhí)行,即一個事務(wù)執(zhí)行完成后,另一個事務(wù)才能開始執(zhí)行。該隔離級別可以解決所有并發(fā)問題,但會嚴重影響數(shù)據(jù)庫的并發(fā)性能,適用于數(shù)據(jù)一致性要求極高但并發(fā)量極低的場景。

1.4.5 隔離級別與并發(fā)問題的關(guān)系

為了更清晰地展示隔離級別與并發(fā)問題的對應(yīng)關(guān)系,以下表格進行了總結(jié):

隔離級別臟讀不可重復(fù)讀幻讀丟失修改
讀未提交可能可能可能可能
讀已提交不可能可能可能可能
可重復(fù)讀不可能不可能MySQL中不可能不可能
串行化不可能不可能不可能不可能

第二章 SpringBoot事務(wù)的核心機制

2.1 Spring事務(wù)管理的核心接口

Spring框架的事務(wù)管理基于一系列核心接口實現(xiàn),這些接口定義了事務(wù)管理的基本規(guī)范,SpringBoot作為Spring的子項目,完全繼承了這些接口的功能,并通過自動配置簡化了其使用。

2.1.1 PlatformTransactionManager

PlatformTransactionManager是Spring事務(wù)管理的核心接口,它定義了事務(wù)的基本操作方法,如獲取事務(wù)、提交事務(wù)、回滾事務(wù)等。該接口是一個抽象層,不同的數(shù)據(jù)庫或持久層框架有其對應(yīng)的實現(xiàn)類,例如:

  • DataSourceTransactionManager:基于JDBC數(shù)據(jù)源的事務(wù)管理器,適用于使用JDBC或MyBatis進行數(shù)據(jù)訪問的場景。
  • HibernateTransactionManager:基于Hibernate的事務(wù)管理器,適用于使用Hibernate進行數(shù)據(jù)訪問的場景。
  • JpaTransactionManager:基于JPA的事務(wù)管理器,適用于使用JPA進行數(shù)據(jù)訪問的場景。

在SpringBoot中,當(dāng)引入spring-boot-starter-jdbc、spring-boot-starter-mybatis等依賴時,SpringBoot會自動配置對應(yīng)的PlatformTransactionManager實現(xiàn)類,開發(fā)者無需手動配置。

2.1.2 TransactionDefinition

TransactionDefinition接口定義了事務(wù)的屬性,如隔離級別、傳播行為、超時時間、是否為只讀事務(wù)等。這些屬性決定了事務(wù)的執(zhí)行規(guī)則,開發(fā)者可以通過配置這些屬性來滿足不同的業(yè)務(wù)需求。

2.1.3 TransactionStatus

TransactionStatus接口用于表示事務(wù)的當(dāng)前狀態(tài),它提供了一系列方法來獲取和修改事務(wù)的狀態(tài),如判斷事務(wù)是否為新事務(wù)、是否已標記為回滾、設(shè)置事務(wù)回滾等。PlatformTransactionManager在執(zhí)行事務(wù)操作時,會通過該接口獲取事務(wù)的狀態(tài)信息,并根據(jù)狀態(tài)執(zhí)行相應(yīng)的操作。

2.2 Spring事務(wù)的傳播行為

事務(wù)的傳播行為是Spring事務(wù)管理中一個非常重要的概念,它定義了當(dāng)一個帶有事務(wù)的方法調(diào)用另一個帶有事務(wù)的方法時,如何處理兩個方法之間的事務(wù)關(guān)系。例如,是沿用當(dāng)前事務(wù),還是創(chuàng)建一個新的事務(wù),或是將當(dāng)前事務(wù)掛起等。Spring定義了7種事務(wù)傳播行為,具體如下:

2.2.1 REQUIRED(默認)

如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前不存在事務(wù),則創(chuàng)建一個新的事務(wù)。這是最常用的傳播行為,適用于大多數(shù)業(yè)務(wù)場景。例如,ServiceA的methodA方法調(diào)用ServiceB的methodB方法,如果methodA已經(jīng)開啟了事務(wù),那么methodB會加入該事務(wù);如果methodA沒有開啟事務(wù),那么methodB會創(chuàng)建一個新的事務(wù)。

2.2.2 SUPPORTS

如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前不存在事務(wù),則以非事務(wù)方式執(zhí)行。該傳播行為適用于那些不需要事務(wù)支持,但如果有事務(wù)也可以加入的方法。例如,一些查詢方法,即使沒有事務(wù)也可以執(zhí)行,但若存在事務(wù)則可以保證數(shù)據(jù)的一致性。

2.2.3 MANDATORY

如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前不存在事務(wù),則拋出異常。該傳播行為強制要求方法必須在事務(wù)中執(zhí)行,適用于那些必須依賴事務(wù)才能保證數(shù)據(jù)一致性的方法。例如,資金轉(zhuǎn)賬的核心方法,必須在事務(wù)中執(zhí)行,否則直接拋出異常。

2.2.4 REQUIRES_NEW

無論當(dāng)前是否存在事務(wù),都創(chuàng)建一個新的事務(wù);如果當(dāng)前存在事務(wù),則將當(dāng)前事務(wù)掛起。該傳播行為適用于那些需要獨立事務(wù)的方法,即使調(diào)用者存在事務(wù),被調(diào)用者的事務(wù)也獨立執(zhí)行,不受調(diào)用者事務(wù)回滾的影響。例如,訂單創(chuàng)建成功后記錄日志的方法,即使訂單創(chuàng)建事務(wù)回滾,日志記錄事務(wù)也應(yīng)該正常提交。

2.2.5 NOT_SUPPORTED

以非事務(wù)方式執(zhí)行;如果當(dāng)前存在事務(wù),則將當(dāng)前事務(wù)掛起。該傳播行為適用于那些不需要事務(wù)支持,且不希望干擾當(dāng)前事務(wù)的方法。例如,一些耗時較長的非核心業(yè)務(wù)操作,如數(shù)據(jù)導(dǎo)出,以非事務(wù)方式執(zhí)行可以提高性能,避免占用事務(wù)資源。

2.2.6 NEVER

以非事務(wù)方式執(zhí)行;如果當(dāng)前存在事務(wù),則拋出異常。該傳播行為強制要求方法必須在非事務(wù)環(huán)境中執(zhí)行,適用于那些絕對不能在事務(wù)中執(zhí)行的方法。例如,某些初始化方法,如果在事務(wù)中執(zhí)行可能會導(dǎo)致數(shù)據(jù)鎖定。

2.2.7 NESTED

如果當(dāng)前存在事務(wù),則在當(dāng)前事務(wù)中創(chuàng)建一個嵌套事務(wù);如果當(dāng)前不存在事務(wù),則創(chuàng)建一個新的事務(wù)。嵌套事務(wù)是當(dāng)前事務(wù)的一個子事務(wù),它依賴于當(dāng)前事務(wù),只有當(dāng)前事務(wù)提交后,嵌套事務(wù)才能提交;如果當(dāng)前事務(wù)回滾,嵌套事務(wù)也會回滾,但嵌套事務(wù)的回滾不會影響當(dāng)前事務(wù)的其他部分。該傳播行為與REQUIRES_NEW的區(qū)別在于,REQUIRES_NEW創(chuàng)建的是完全獨立的事務(wù),而NESTED創(chuàng)建的是依賴于父事務(wù)的子事務(wù)。

2.3 SpringBoot事務(wù)的實現(xiàn)方式

SpringBoot支持兩種事務(wù)管理方式:編程式事務(wù)和聲明式事務(wù)。編程式事務(wù)需要開發(fā)者手動編寫代碼來控制事務(wù)的開啟、提交和回滾,靈活性高但代碼侵入性強;聲明式事務(wù)通過注解或XML配置的方式實現(xiàn)事務(wù)管理,代碼侵入性低,是SpringBoot開發(fā)中推薦使用的方式。

2.3.1 編程式事務(wù)

編程式事務(wù)通過Spring提供的TransactionTemplate或直接使用PlatformTransactionManager來實現(xiàn)。TransactionTemplate是對編程式事務(wù)的封裝,簡化了事務(wù)操作的代碼。

示例代碼如下(基于TransactionTemplate):

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;
@Service
public class OrderService {
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private StockMapper stockMapper;
    @Autowired
    private TransactionTemplate transactionTemplate;
    public void createOrder(Order order) {
        // 使用TransactionTemplate執(zhí)行事務(wù)
        transactionTemplate.execute(status -> {
            try {
                // 扣減庫存
                stockMapper.reduceStock(order.getProductId(), order.getQuantity());
                // 創(chuàng)建訂單
                orderMapper.insertOrder(order);
                return true;
            } catch (Exception e) {
                // 事務(wù)回滾
                status.setRollbackOnly();
                e.printStackTrace();
                return false;
            }
        });
    }
}

編程式事務(wù)的優(yōu)點是可以精確控制事務(wù)的邊界和執(zhí)行邏輯,適用于復(fù)雜的事務(wù)場景;缺點是需要在業(yè)務(wù)代碼中嵌入事務(wù)管理代碼,增加了代碼的耦合度。

2.3.2 聲明式事務(wù)

聲明式事務(wù)基于AOP(面向切面編程)實現(xiàn),通過注解或XML配置的方式將事務(wù)管理邏輯與業(yè)務(wù)邏輯分離,開發(fā)者只需在需要事務(wù)支持的方法上添加注解即可實現(xiàn)事務(wù)管理。SpringBoot推薦使用@Transactional注解實現(xiàn)聲明式事務(wù)。

使用聲明式事務(wù)的步驟非常簡單:

  • 在SpringBoot啟動類上添加@EnableTransactionManagement注解(SpringBoot 2.0+版本可省略該注解,因為其會自動識別事務(wù)相關(guān)依賴并開啟事務(wù)管理)。
  • 在需要事務(wù)支持的Service方法上添加@Transactional注解。

示例代碼如下:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class OrderService {
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private StockMapper stockMapper;
    // 添加@Transactional注解開啟事務(wù)
    @Transactional
    public void createOrder(Order order) {
        // 扣減庫存
        stockMapper.reduceStock(order.getProductId(), order.getQuantity());
        // 創(chuàng)建訂單
        orderMapper.insertOrder(order);
        // 如果出現(xiàn)異常,事務(wù)會自動回滾
        if (order.getQuantity() <= 0) {
            throw new IllegalArgumentException("訂單數(shù)量不能小于等于0");
        }
    }
}

聲明式事務(wù)的優(yōu)點是代碼侵入性低,事務(wù)管理邏輯與業(yè)務(wù)邏輯分離,提高了代碼的可讀性和可維護性;缺點是事務(wù)控制的粒度相對較粗,無法精確控制事務(wù)的執(zhí)行邏輯。

第三章 SpringBoot聲明式事務(wù)的使用詳解

3.1 @Transactional注解的核心屬性

@Transactional注解提供了多個屬性,用于配置事務(wù)的傳播行為、隔離級別、超時時間等,開發(fā)者可以根據(jù)業(yè)務(wù)需求靈活配置。以下是常用的核心屬性:

3.1.1 propagation:事務(wù)傳播行為

用于指定事務(wù)的傳播行為,默認值為Propagation.REQUIRED??梢酝ㄟ^Propagation枚舉類指定其他傳播行為,例如:

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void logOrderCreate(Order order) {
    // 記錄訂單創(chuàng)建日志,該方法會創(chuàng)建新的事務(wù)
    logMapper.insertOrderLog(order.getId(), "訂單創(chuàng)建成功");
}

3.1.2 isolation:事務(wù)隔離級別

用于指定事務(wù)的隔離級別,默認值為Isolation.DEFAULT,即使用數(shù)據(jù)庫的默認隔離級別??梢酝ㄟ^Isolation枚舉類指定其他隔離級別,例如:

@Transactional(isolation = Isolation.REPEATABLE_READ)
public List<Order> queryOrderByUserId(Long userId) {
    // 查詢用戶的訂單,使用可重復(fù)讀隔離級別
    return orderMapper.selectByUserId(userId);
}

3.1.3 timeout:事務(wù)超時時間

用于指定事務(wù)的超時時間,單位為秒,默認值為-1,表示不設(shè)置超時時間(即使用數(shù)據(jù)庫的默認超時時間)。如果事務(wù)執(zhí)行時間超過指定的超時時間,事務(wù)會自動回滾。例如:

@Transactional(timeout = 30)
public void batchImportData(List<Data> dataList) {
    // 批量導(dǎo)入數(shù)據(jù),事務(wù)超時時間為30秒
    dataMapper.batchInsert(dataList);
}

3.1.4 readOnly:是否為只讀事務(wù)

用于指定事務(wù)是否為只讀事務(wù),默認值為false。如果將該屬性設(shè)置為true,數(shù)據(jù)庫會對事務(wù)進行優(yōu)化,提高查詢性能,但此時事務(wù)中不能執(zhí)行修改數(shù)據(jù)的操作(如插入、更新、刪除),否則會拋出異常。該屬性適用于純查詢的業(yè)務(wù)方法,例如:

@Transactional(readOnly = true)
public Order queryOrderById(Long orderId) {
    // 純查詢方法,設(shè)置為只讀事務(wù)
    return orderMapper.selectById(orderId);
}

3.1.5 rollbackFor:指定需要回滾的異常類型

默認情況下,Spring事務(wù)只在遇到運行時異常(RuntimeException)和錯誤(Error)時才會回滾事務(wù),對于編譯時異常不會回滾。通過rollbackFor屬性可以指定需要回滾的異常類型,例如:

@Transactional(rollbackFor = Exception.class)
public void updateOrderStatus(Long orderId, Integer status) throws Exception {
    // 該方法拋出任何Exception類型的異常,事務(wù)都會回滾
    Order order = orderMapper.selectById(orderId);
    if (order == null) {
        throw new Exception("訂單不存在");
    }
    order.setStatus(status);
    orderMapper.update(order);
}

3.1.6 noRollbackFor:指定不需要回滾的異常類型

與rollbackFor屬性相反,noRollbackFor屬性用于指定不需要回滾的異常類型,即使該異常是運行時異常,事務(wù)也不會回滾。例如:

@Transactional(noRollbackFor = BusinessException.class)
public void processOrder(Order order) {
    try {
        // 業(yè)務(wù)處理邏輯
    } catch (BusinessException e) {
        // 拋出BusinessException時,事務(wù)不回滾
        e.printStackTrace();
    }
}

3.2 @Transactional注解的使用位置

@Transactional注解可以用于類上或方法上,其作用范圍有所不同:

3.2.1 用于類上

當(dāng)@Transactional注解用于類上時,該注解會作用于類中的所有公共(public)方法,即類中的所有public方法都會開啟事務(wù)。如果類中的某個方法需要特殊的事務(wù)配置,可以在該方法上單獨添加@Transactional注解,方法上的注解會覆蓋類上的注解配置。例如:

@Service
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public class OrderService {
    // 繼承類上的事務(wù)配置
    public void createOrder(Order order) {
        // 業(yè)務(wù)邏輯
    }
    // 覆蓋類上的事務(wù)配置,使用REQUIRES_NEW傳播行為
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void logOrderCreate(Order order) {
        // 業(yè)務(wù)邏輯
    }
}

3.2.2 用于方法上

當(dāng)@Transactional注解用于方法上時,該注解只作用于當(dāng)前方法。需要注意的是,@Transactional注解只能作用于公共(public)方法,對于非public方法(如private、protected、default修飾的方法),注解不會生效,因為Spring AOP只能代理public方法。

3.3 事務(wù)的嵌套調(diào)用場景分析

在實際開發(fā)中,經(jīng)常會遇到事務(wù)方法嵌套調(diào)用的場景,不同的傳播行為會導(dǎo)致不同的事務(wù)執(zhí)行結(jié)果。以下通過幾個典型場景分析事務(wù)的嵌套調(diào)用邏輯:

3.3.1 場景一:同一Service內(nèi)的事務(wù)方法嵌套

在同一Service類中,帶有事務(wù)的methodA方法調(diào)用帶有事務(wù)的methodB方法,此時由于Spring AOP的代理機制,methodB方法上的@Transactional注解不會生效,事務(wù)的傳播行為由methodA方法的配置決定。例如:

@Service
public class OrderService {
    @Transactional(propagation = Propagation.REQUIRED)
    public void methodA(Order order) {
        // 調(diào)用同一類中的methodB方法
        methodB(order);
        // 業(yè)務(wù)邏輯
    }
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void methodB(Order order) {
        // 業(yè)務(wù)邏輯
    }
}

上述代碼中,methodA調(diào)用methodB時,由于是內(nèi)部方法調(diào)用,沒有通過Spring的代理對象,因此methodB上的@Transactional注解不會生效,methodB會加入methodA的事務(wù)中,而不會創(chuàng)建新的事務(wù)。如果需要methodB的事務(wù)注解生效,可以通過以下兩種方式解決:

  • 將methodB方法提取到另一個Service類中,通過依賴注入的方式調(diào)用。
  • 在當(dāng)前Service類中通過@Autowired注入自身的代理對象,使用代理對象調(diào)用methodB方法。

方式二的示例代碼如下:

@Service
public class OrderService {
    @Autowired
    private OrderService orderService; // 注入自身的代理對象
    @Transactional(propagation = Propagation.REQUIRED)
    public void methodA(Order order) {
        // 使用代理對象調(diào)用methodB方法
        orderService.methodB(order);
        // 業(yè)務(wù)邏輯
    }
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void methodB(Order order) {
        // 業(yè)務(wù)邏輯
    }
}

3.3.2 場景二:不同Service間的事務(wù)方法嵌套(REQUIRED傳播行為)

ServiceA的methodA方法(REQUIRED傳播行為)調(diào)用ServiceB的methodB方法(REQUIRED傳播行為),此時methodB會加入methodA的事務(wù)中,兩者共用一個事務(wù)。如果methodA或methodB中出現(xiàn)異常,整個事務(wù)會回滾。例如:

@Service
public class ServiceA {
    @Autowired
    private ServiceB serviceB;
    @Transactional(propagation = Propagation.REQUIRED)
    public void methodA() {
        // 業(yè)務(wù)邏輯A
        serviceB.methodB();
        // 如果此處拋出異常,methodA和methodB的操作都會回滾
        throw new RuntimeException("methodA異常");
    }
}
@Service
public class ServiceB {
    @Transactional(propagation = Propagation.REQUIRED)
    public void methodB() {
        // 業(yè)務(wù)邏輯B
    }
}

上述代碼中,methodA調(diào)用methodB后拋出異常,由于兩者共用一個事務(wù),因此methodA和methodB的操作都會回滾。

3.3.3 場景三:不同Service間的事務(wù)方法嵌套(REQUIRES_NEW傳播行為)

ServiceA的methodA方法(REQUIRED傳播行為)調(diào)用ServiceB的methodB方法(REQUIRES_NEW傳播行為),此時methodB會創(chuàng)建一個新的事務(wù),與methodA的事務(wù)相互獨立。如果methodA中出現(xiàn)異常,methodA的事務(wù)會回滾,但methodB的事務(wù)不會受影響;如果methodB中出現(xiàn)異常,methodB的事務(wù)會回滾,同時異常會傳播到methodA,導(dǎo)致methodA的事務(wù)也回滾。例如:

@Service
public class ServiceA {
    @Autowired
    private ServiceB serviceB;
    @Transactional(propagation = Propagation.REQUIRED)
    public void methodA() {
        // 業(yè)務(wù)邏輯A
        serviceB.methodB();
        // 如果此處拋出異常,methodA的操作回滾,methodB的操作已提交不會回滾
        throw new RuntimeException("methodA異常");
    }
}
@Service
public class ServiceB {
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void methodB() {
        // 業(yè)務(wù)邏輯B,執(zhí)行完成后會提交事務(wù)
    }
}

上述代碼中,methodB執(zhí)行完成后會提交自己的事務(wù),隨后methodA拋出異常,methodA的事務(wù)回滾,但methodB的事務(wù)已經(jīng)提交,因此methodB的操作不會回滾。

第四章 SpringBoot事務(wù)的常見問題與解決方案

4.1 事務(wù)不生效的常見原因

在使用SpringBoot事務(wù)的過程中,經(jīng)常會遇到事務(wù)不生效的問題,即方法執(zhí)行出現(xiàn)異常后,事務(wù)沒有回滾。以下是事務(wù)不生效的常見原因及解決方案:

4.1.1 方法不是public修飾的

Spring AOP只能代理public方法,@Transactional注解只對public方法生效。如果將注解添加到非public方法上,事務(wù)不會生效。

解決方案:將需要事務(wù)支持的方法改為public修飾。

4.1.2 異常類型不匹配

默認情況下,Spring事務(wù)只在遇到RuntimeException和Error時才會回滾,如果方法拋出的是編譯時異常(如IOException、SQLException等),事務(wù)不會回滾。

解決方案:通過@Transactional注解的rollbackFor屬性指定需要回滾的異常類型,例如rollbackFor = Exception.class。

4.1.3 異常被手動捕獲且未重新拋出

如果在事務(wù)方法中手動捕獲了異常,并且沒有將異常重新拋出,Spring無法感知到異常的發(fā)生,因此不會觸發(fā)事務(wù)回滾。例如:

@Transactional
public void createOrder(Order order) {
    try {
        stockMapper.reduceStock(order.getProductId(), order.getQuantity());
        orderMapper.insertOrder(order);
    } catch (Exception e) {
        // 捕獲異常但未重新拋出,事務(wù)不會回滾
        e.printStackTrace();
    }
}

解決方案:在catch塊中重新拋出異常,或者通過TransactionStatus的setRollbackOnly()方法手動標記事務(wù)回滾。修改后的代碼如下:

@Transactional
public void createOrder(Order order) {
    try {
        stockMapper.reduceStock(order.getProductId(), order.getQuantity());
        orderMapper.insertOrder(order);
    } catch (Exception e) {
        e.printStackTrace();
        // 重新拋出異常,觸發(fā)事務(wù)回滾
        throw new RuntimeException("創(chuàng)建訂單失敗", e);
    }
}

4.1.4 同一Service內(nèi)的內(nèi)部方法調(diào)用

如3.3.1節(jié)所述,同一Service類中,事務(wù)方法調(diào)用另一個事務(wù)方法時,由于是內(nèi)部方法調(diào)用,沒有通過Spring的代理對象,因此被調(diào)用方法上的@Transactional注解不會生效。

解決方案:將被調(diào)用的事務(wù)方法提取到另一個Service類中,或者在當(dāng)前Service類中注入自身的代理對象進行調(diào)用。

4.1.5 數(shù)據(jù)源未配置事務(wù)管理器

SpringBoot需要為數(shù)據(jù)源配置對應(yīng)的事務(wù)管理器(如DataSourceTransactionManager)才能實現(xiàn)事務(wù)管理。如果數(shù)據(jù)源沒有配置事務(wù)管理器,事務(wù)不會生效。

解決方案:確保項目中引入了對應(yīng)的數(shù)據(jù)源依賴(如spring-boot-starter-jdbc),SpringBoot會自動配置事務(wù)管理器。如果是自定義數(shù)據(jù)源,需要手動配置事務(wù)管理器,示例代碼如下:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
@Configuration
public class TransactionConfig {
    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
}

4.1.6 事務(wù)傳播行為配置錯誤

如果事務(wù)傳播行為配置不當(dāng),也可能導(dǎo)致事務(wù)不生效。例如,將傳播行為配置為NOT_SUPPORTED或NEVER,會導(dǎo)致方法以非事務(wù)方式執(zhí)行。

解決方案:根據(jù)業(yè)務(wù)場景選擇合適的事務(wù)傳播行為,大多數(shù)場景下使用默認的REQUIRED即可。

4.2 事務(wù)回滾異常的處理技巧

在實際開發(fā)中,有時需要根據(jù)不同的業(yè)務(wù)場景靈活控制事務(wù)的回滾邏輯,以下是一些事務(wù)回滾異常的處理技巧:

4.2.1 手動標記事務(wù)回滾

如果需要在不拋出異常的情況下手動觸發(fā)事務(wù)回滾,可以通過TransactionStatus對象的setRollbackOnly()方法實現(xiàn)。例如,在某些業(yè)務(wù)場景下,雖然沒有發(fā)生異常,但根據(jù)業(yè)務(wù)規(guī)則需要回滾事務(wù):

import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.transaction.support.TransactionStatus;
@Service
public class OrderService {
    @Transactional
    public void createOrder(Order order) {
        // 獲取當(dāng)前事務(wù)狀態(tài)
        TransactionStatus status = TransactionSynchronizationManager.getCurrentTransactionStatus();
        // 業(yè)務(wù)邏輯處理
        boolean isSuccess = checkBusinessRule(order);
        if (!isSuccess) {
            // 手動標記事務(wù)回滾
            status.setRollbackOnly();
            return;
        }
        stockMapper.reduceStock(order.getProductId(), order.getQuantity());
        orderMapper.insertOrder(order);
    }
    private boolean checkBusinessRule(Order order) {
        // 業(yè)務(wù)規(guī)則校驗
        return order.getAmount() > 0;
    }
}

4.2.2 自定義異常與事務(wù)回滾

在實際開發(fā)中,通常會定義自定義的業(yè)務(wù)異常來表示不同的業(yè)務(wù)錯誤。為了讓自定義異常能夠觸發(fā)事務(wù)回滾,需要在@Transactional注解的rollbackFor屬性中指定自定義異常類型,或者讓自定義異常繼承RuntimeException(因為Spring默認對RuntimeException回滾)。

示例代碼如下(自定義異常繼承RuntimeException):

// 自定義業(yè)務(wù)異常
public class BusinessException extends RuntimeException {
    public BusinessException(String message) {
        super(message);
    }
}
@Service
public class OrderService {
    @Transactional
    public void createOrder(Order order) {
        if (order.getQuantity() <= 0) {
            // 拋出自定義異常,觸發(fā)事務(wù)回滾
            throw new BusinessException("訂單數(shù)量不能小于等于0");
        }
        stockMapper.reduceStock(order.getProductId(), order.getQuantity());
        orderMapper.insertOrder(order);
    }
}

4.3 高并發(fā)場景下的事務(wù)優(yōu)化

在高并發(fā)場景下,事務(wù)的使用不當(dāng)可能會導(dǎo)致數(shù)據(jù)庫性能下降、死鎖等問題,以下是一些高并發(fā)場景下的事務(wù)優(yōu)化技巧:

4.3.1 縮小事務(wù)范圍

事務(wù)的執(zhí)行時間越長,占用的數(shù)據(jù)庫資源越多,并發(fā)性能越低,同時出現(xiàn)死鎖的風(fēng)險也越高。因此,應(yīng)盡量縮小事務(wù)的范圍,只將核心的數(shù)據(jù)庫操作包含在事務(wù)中,避免在事務(wù)中執(zhí)行耗時操作(如網(wǎng)絡(luò)請求、文件IO、復(fù)雜計算等)。

優(yōu)化前的代碼(事務(wù)中包含耗時操作):

@Transactional
public void createOrder(Order order) {
    // 耗時的網(wǎng)絡(luò)請求(不應(yīng)包含在事務(wù)中)
    User user = userFeignClient.getUserById(order.getUserId());
    if (user == null) {
        throw new BusinessException("用戶不存在");
    }
    // 核心數(shù)據(jù)庫操作
    stockMapper.reduceStock(order.getProductId(), order.getQuantity());
    orderMapper.insertOrder(order);
}

優(yōu)化后的代碼(將耗時操作移出事務(wù)):

public void createOrder(Order order) {
    // 耗時的網(wǎng)絡(luò)請求(移出事務(wù))
    User user = userFeignClient.getUserById(order.getUserId());
    if (user == null) {
        throw new BusinessException("用戶不存在");
    }
    // 調(diào)用事務(wù)方法執(zhí)行核心數(shù)據(jù)庫操作
    doCreateOrder(order);
}
@Transactional
public void doCreateOrder(Order order) {
    // 核心數(shù)據(jù)庫操作
    stockMapper.reduceStock(order.getProductId(), order.getQuantity());
    orderMapper.insertOrder(order);
}

4.3.2 使用合適的隔離級別

隔離級別越高,數(shù)據(jù)一致性越好,但并發(fā)性能越低。在高并發(fā)場景下,應(yīng)在保證數(shù)據(jù)一致性的前提下,盡量選擇較低的隔離級別。例如,大多數(shù)業(yè)務(wù)場景下使用讀已提交(Read Committed)隔離級別即可,既能避免臟讀,又能保證較好的并發(fā)性能。

配置示例:

@Transactional(isolation = Isolation.READ_COMMITTED)
public void createOrder(Order order) {
    // 業(yè)務(wù)邏輯
}

4.3.3 避免事務(wù)中的鎖競爭

在高并發(fā)場景下,事務(wù)中的鎖競爭是導(dǎo)致性能下降的主要原因之一。為了避免鎖競爭,可以采取以下措施:

  • 盡量使用行鎖,避免使用表鎖。例如,在執(zhí)行更新操作時,盡量通過主鍵或唯一索引定位數(shù)據(jù),避免全表掃描導(dǎo)致的表鎖。
  • 控制事務(wù)的執(zhí)行順序,避免不同事務(wù)交叉更新同一批數(shù)據(jù)導(dǎo)致死鎖。例如,多個事務(wù)都需要更新A和B兩條數(shù)據(jù)時,都按照先更新A再更新B的順序執(zhí)行。
  • 使用樂觀鎖替代悲觀鎖。樂觀鎖通過版本號或時間戳機制實現(xiàn),不需要在事務(wù)中持有鎖,適用于讀多寫少的高并發(fā)場景。

樂觀鎖示例(基于版本號):

// 實體類添加版本號字段
public class Stock {
    private Long id;
    private Long productId;
    private Integer quantity;
    private Integer version; // 版本號字段
    // getter和setter
}
// Mapper接口
public interface StockMapper {
    // 樂觀鎖更新:只有版本號匹配時才更新
    int reduceStockWithVersion(@Param("productId") Long productId, 
                               @Param("quantity") Integer quantity, 
                               @Param("version") Integer version);
}
// XML映射文件
<update id="reduceStockWithVersion">
    UPDATE stock 
    SET quantity = quantity - #{quantity}, version = version + 1 
    WHERE product_id = #{productId} AND version = #{version}
</update>
// Service方法
@Transactional
public void reduceStock(Long productId, Integer quantity) {
    // 查詢庫存和版本號
    Stock stock = stockMapper.selectByProductId(productId);
    if (stock == null || stock.getQuantity() < quantity) {
        throw new BusinessException("庫存不足");
    }
    // 樂觀鎖更新
    int rows = stockMapper.reduceStockWithVersion(productId, quantity, stock.getVersion());
    if (rows == 0) {
        // 更新失敗,說明庫存已被其他事務(wù)修改,拋出異?;蛑卦?
        throw new BusinessException("庫存更新失敗,請重試");
    }
}

4.3.4 使用事務(wù)超時機制

在高并發(fā)場景下,部分事務(wù)可能由于資源競爭等原因?qū)е聢?zhí)行時間過長,占用大量數(shù)據(jù)庫資源。通過設(shè)置事務(wù)超時時間,可以讓長時間未執(zhí)行完成的事務(wù)自動回滾,釋放數(shù)據(jù)庫資源。

配置示例:

@Transactional(timeout = 10) // 事務(wù)超時時間為10秒
public void batchProcessData(List<Data> dataList) {
    // 批量處理數(shù)據(jù)的業(yè)務(wù)邏輯
}

第五章 總結(jié)與拓展

5.1 文章知識點總結(jié)

本文圍繞SpringBoot事務(wù)展開,從基礎(chǔ)理論到實踐應(yīng)用進行了全面講解,核心知識點總結(jié)如下:事務(wù)基礎(chǔ)層面,明確了事務(wù)的定義及ACID四大核心特性,深入分析了臟讀、不可重復(fù)讀等并發(fā)問題及對應(yīng)的數(shù)據(jù)庫隔離級別,為后續(xù)SpringBoot事務(wù)的學(xué)習(xí)奠定理論基礎(chǔ);核心機制層面,剖析了Spring事務(wù)管理的三大核心接口,詳細解讀了7種事務(wù)傳播行為的適用場景,對比了編程式與聲明式兩種事務(wù)實現(xiàn)方式的優(yōu)劣;使用詳解層面,聚焦聲明式事務(wù)的@Transactional注解,梳理了核心屬性的配置方法、注解使用位置及嵌套調(diào)用場景;問題解決層面,歸納了事務(wù)不生效的常見原因及解決方案,提供了事務(wù)回滾異常的處理技巧,并給出高并發(fā)場景下的事務(wù)優(yōu)化策略。通過理論與代碼示例結(jié)合的方式,構(gòu)建了完整的SpringBoot事務(wù)知識體系。

5.2 知識拓展與延伸

除了本文講解的核心內(nèi)容,SpringBoot事務(wù)還有一些進階知識點值得關(guān)注。例如,分布式事務(wù)問題,在微服務(wù)架構(gòu)中,跨服務(wù)的事務(wù)操作無法依賴單一數(shù)據(jù)庫的事務(wù)機制,此時需要引入Seata、Saga等分布式事務(wù)解決方案;又如,事務(wù)同步機制,Spring提供的TransactionSynchronization接口可以在事務(wù)提交或回滾的不同階段執(zhí)行自定義邏輯,適用于事務(wù)完成后發(fā)送消息、更新緩存等場景。此外,SpringBoot 3.x版本中對事務(wù)管理的自動配置進行了優(yōu)化,結(jié)合Jakarta EE的規(guī)范調(diào)整了相關(guān)API,開發(fā)者在升級框架時需注意適配。

5.3 推薦閱讀資料

為幫助大家進一步深化對SpringBoot事務(wù)及相關(guān)技術(shù)的理解,推薦以下優(yōu)質(zhì)資料:

  • 官方文檔:Spring Framework官方文檔的“Transaction Management”章節(jié),是最權(quán)威的學(xué)習(xí)資料,詳細闡述了Spring事務(wù)的設(shè)計理念與實現(xiàn)細節(jié)

到此這篇關(guān)于SpringBoot 事務(wù)深度解析之從理論到實踐的完整指南的文章就介紹到這了,更多相關(guān)SpringBoot 事務(wù)全解析內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Spring Boot 日志配置詳解:log4j2.xml 的完整配置指南

    Spring Boot 日志配置詳解:log4j2.xml 的完整配置指南

    本文介紹了在SpringBoot項目中配置Log4j2的方法,包括選擇Log4j2的原因、Maven依賴配置、application.yml配置、log4j2.xml完整配置詳解,以及性能優(yōu)化建議,通過合理配置,可以構(gòu)建高性能的異步日志記錄系統(tǒng),滿足日常開發(fā)和運維需求
    2026-04-04
  • 簡單聊聊Java中驗證碼功能的實現(xiàn)

    簡單聊聊Java中驗證碼功能的實現(xiàn)

    相信大家都經(jīng)常接觸到驗證碼的,畢竟平時上網(wǎng)也能遇到各種驗證碼,需要我們輸入驗證碼進行驗證我們是人類,本篇文章就從這幾個方面出發(fā)說說驗證碼,廢話不多說,下面開始正文
    2023-06-06
  • Java內(nèi)存模型JMM與volatile

    Java內(nèi)存模型JMM與volatile

    這篇文章主要介紹了Java內(nèi)存模型JMM與volatile,Java內(nèi)存模型是一種抽象的概念,并不真實存在,它描述的是一組規(guī)則或規(guī)范,定義了程序中各個變量的訪問方式
    2022-07-07
  • Java ResultSet案例講解

    Java ResultSet案例講解

    這篇文章主要介紹了Java ResultSet案例講解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • mac配置idea maven全過程

    mac配置idea maven全過程

    本文主要介紹了在Mac上配置IDEA和Maven的過程,包括下載Maven、編輯setting.xml文件、配置Maven和IDEA的相關(guān)路徑等步驟
    2026-04-04
  • 一篇文章帶你了解Java Stream流

    一篇文章帶你了解Java Stream流

    Stream流是數(shù)據(jù)渠道,用于操作數(shù)據(jù)源(集合、數(shù)組等)所生成的元素序列。這篇文章主要介紹了Java8新特性Stream流的相關(guān)資料,需要的朋友參考下吧
    2021-08-08
  • Java transient關(guān)鍵字與序列化操作實例詳解

    Java transient關(guān)鍵字與序列化操作實例詳解

    這篇文章主要介紹了Java transient關(guān)鍵字與序列化操作,結(jié)合實例形式詳細分析了java序列化操作相關(guān)實現(xiàn)方法與操作注意事項,需要的朋友可以參考下
    2019-09-09
  • SpringBoot獲取Request和Response方法代碼解析

    SpringBoot獲取Request和Response方法代碼解析

    這篇文章主要介紹了SpringBoot獲取Request和Response方法代碼解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-11-11
  • 解決Mybatis在IDEA中找不到mapper映射文件的問題

    解決Mybatis在IDEA中找不到mapper映射文件的問題

    這篇文章主要介紹了解決Mybatis在IDEA中找不到mapper映射文件的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-10-10
  • java操作mongodb基礎(chǔ)(查詢 排序 輸出list)

    java操作mongodb基礎(chǔ)(查詢 排序 輸出list)

    java操作mongodb基礎(chǔ)學(xué)習(xí)查詢,排序,limit,輸出為list實例,大家參考使用吧
    2013-12-12

最新評論

定南县| 长汀县| 巨野县| 东方市| 右玉县| 庆元县| 渭源县| 高平市| 博湖县| 滦平县| 黑龙江省| 蓬溪县| 中牟县| 菏泽市| 和硕县| 宜兰县| 台北县| 石渠县| 泊头市| 梓潼县| 崇州市| 盐边县| 鲜城| 太原市| 同德县| 合江县| 沙雅县| 隆林| 榕江县| 贵定县| 辉县市| 丰原市| 鄂州市| 仙居县| 甘肃省| 嘉定区| 封开县| 芦山县| 惠来县| 陆良县| 大丰市|