Spring實現(xiàn)方式、隔離級別與傳播機(jī)制全攻略
在后端開發(fā)中,數(shù)據(jù)一致性是核心訴求之一。無論是轉(zhuǎn)賬時的金額流轉(zhuǎn),還是秒殺場景的庫存扣減,稍有不慎就會導(dǎo)致數(shù)據(jù)錯亂 —— 比如 A 賬戶扣款成功但 B 賬戶未到賬,下單成功但庫存未減少。而事務(wù),正是解決這類問題的關(guān)鍵技術(shù)。Spring 框架對事務(wù)進(jìn)行了高度封裝,提供了靈活易用的事務(wù)管理能力。本文將從事務(wù)基礎(chǔ)出發(fā),深入拆解 Spring 事務(wù)的實現(xiàn)方式、核心注解配置、隔離級別,并重點剖析事務(wù)傳播機(jī)制的 7 種行為與實際應(yīng)用場景,幫你徹底掌握 Spring 事務(wù)的核心用法。
一、事務(wù)基礎(chǔ)回顧:是什么?為什么需要?
在學(xué)習(xí) Spring 事務(wù)之前,我們先回顧數(shù)據(jù)庫事務(wù)的核心概念,這是理解 Spring 事務(wù)的基礎(chǔ)。
1.1 事務(wù)的定義
事務(wù)是一組不可分割的數(shù)據(jù)庫操作集合,這組操作要么全部成功執(zhí)行并提交,要么全部失敗并回滾,不存在 “部分成功” 的中間狀態(tài)。就像快遞發(fā)貨,下單、扣庫存、生成物流單這一系列操作,必須同時完成才算交易成功,任何一步失敗都要回到初始狀態(tài)。
1.2 為什么需要事務(wù)?
事務(wù)的核心價值是保證數(shù)據(jù)一致性,我們通過兩個經(jīng)典場景理解:
- 轉(zhuǎn)賬場景:A 賬戶轉(zhuǎn)出 100 元,B 賬戶轉(zhuǎn)入 100 元。如果沒有事務(wù),A 賬戶扣款成功后,B 賬戶轉(zhuǎn)入操作失敗,會導(dǎo)致 100 元 “憑空消失”;
- 秒殺場景:用戶下單成功后,需要扣減對應(yīng)商品庫存。如果下單成功但庫存扣減失敗,會導(dǎo)致超賣(實際庫存為 0 但仍有訂單生成)。
事務(wù)通過 “原子性” 特性,確保這一系列操作要么全成,要么全敗,從根本上避免數(shù)據(jù)不一致。
1.3 事務(wù)的核心操作
數(shù)據(jù)庫層面,事務(wù)的操作有三步,Spring 事務(wù)本質(zhì)也是對這三步的封裝:
- 開啟事務(wù):
start transaction / begin(操作執(zhí)行前開啟); - 提交事務(wù):
commit(所有操作無異常時提交,數(shù)據(jù)永久生效); - 回滾事務(wù):
rollback(任意操作異常時回滾,恢復(fù)到操作前狀態(tài))。
二、Spring 事務(wù)的兩種實現(xiàn)方式
Spring 支持兩種事務(wù)管理方式:編程式事務(wù)(手動控制)和聲明式事務(wù)(注解自動控制)。實際開發(fā)中,聲明式事務(wù)因簡潔高效成為主流,編程式事務(wù)僅用于特殊場景。
2.1 編程式事務(wù):手動控制事務(wù)生命周期
編程式事務(wù)需要開發(fā)者手動編寫代碼開啟、提交、回滾事務(wù),靈活性高但代碼繁瑣。
核心依賴與組件
SpringBoot 內(nèi)置了DataSourceTransactionManager(事務(wù)管理器),無需額外引入依賴,核心組件:
DataSourceTransactionManager:負(fù)責(zé)事務(wù)的開啟、提交、回滾;TransactionDefinition:定義事務(wù)屬性(如隔離級別、傳播機(jī)制);TransactionStatus:事務(wù)的當(dāng)前狀態(tài)(如是否活躍、是否需要回滾)。
代碼實現(xiàn)(以用戶注冊為例)
- 準(zhǔn)備工作:創(chuàng)建數(shù)據(jù)庫表(用戶表
user_info、日志表log_info)、實體類、Mapper 接口(文檔中已提供,此處省略); - Controller 層手動控制事務(wù):
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/user")
public class UserController {
// 注入事務(wù)管理器
@Autowired
private DataSourceTransactionManager transactionManager;
// 注入事務(wù)屬性定義
@Autowired
private TransactionDefinition transactionDefinition;
// 注入業(yè)務(wù)層
@Autowired
private UserService userService;
@RequestMapping("/registry")
public String registry(String name, String password) {
// 1. 開啟事務(wù)
TransactionStatus status = transactionManager.getTransaction(transactionDefinition);
try {
// 2. 執(zhí)行核心業(yè)務(wù)(用戶注冊)
userService.registryUser(name, password);
// 3. 無異常,提交事務(wù)
transactionManager.commit(status);
return "注冊成功";
} catch (Exception e) {
// 4. 有異常,回滾事務(wù)
transactionManager.rollback(status);
return "注冊失敗";
}
}
}優(yōu)缺點
- 優(yōu)點:完全手動控制事務(wù)邊界,靈活處理復(fù)雜場景;
- 缺點:代碼冗余,事務(wù)邏輯與業(yè)務(wù)邏輯耦合,不利于維護(hù)。
2.2 聲明式事務(wù):@Transactional 注解一鍵搞定
聲明式事務(wù)基于 AOP 實現(xiàn),通過@Transactional注解自動完成事務(wù)的開啟、提交、回滾,無需編寫額外事務(wù)代碼,是 Spring 事務(wù)的推薦用法。
實現(xiàn)步驟
- 引入依賴(SpringBoot 項目已內(nèi)置
spring-tx,無需手動引入):
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
</dependency>- 在需要事務(wù)的方法 / 類上添加
@Transactional注解:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/trans")
public class TransactionalController {
@Autowired
private UserService userService;
// 添加入注解,該方法自動支持事務(wù)
@Transactional
@RequestMapping("/registry")
public String registry(String name, String password) {
// 執(zhí)行核心業(yè)務(wù)
userService.registryUser(name, password);
// 模擬異常(測試回滾)
int a = 10 / 0;
return "注冊成功";
}
}核心原理
- 當(dāng)方法被
@Transactional修飾時,Spring 會通過 AOP 動態(tài)生成代理對象; - 方法執(zhí)行前,代理對象自動開啟事務(wù);
- 方法執(zhí)行無異常時,自動提交事務(wù);
- 方法拋出未捕獲的異常時,自動回滾事務(wù)。
注意事項
@Transactional僅對public方法生效(修飾非 public 方法時不報錯但無事務(wù)效果);- 若異常被
try-catch捕獲且未重新拋出,事務(wù)不會回滾(Spring 無法感知異常); - 建議在業(yè)務(wù)層(Service) 使用該注解(業(yè)務(wù)層通常包含多個數(shù)據(jù)操作,便于控制事務(wù)邊界)。
異常捕獲后的回滾方案
如果需要捕獲異常且讓事務(wù)回滾,有兩種方式:
- 重新拋出異常:
@Transactional
public String registry(String name, String password) {
try {
userService.registryUser(name, password);
int a = 10 / 0;
} catch (Exception e) {
e.printStackTrace();
// 重新拋出異常,觸發(fā)回滾
throw e;
}
return "注冊成功";
}
- 手動觸發(fā)回滾:
import org.springframework.transaction.interceptor.TransactionAspectSupport;
@Transactional
public String registry(String name, String password) {
try {
userService.registryUser(name, password);
int a = 10 / 0;
} catch (Exception e) {
e.printStackTrace();
// 手動回滾事務(wù)
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
return "注冊成功";
}三、@Transactional 注解詳解:三大核心屬性
@Transactional注解提供了多個屬性,用于靈活配置事務(wù)行為,核心屬性有 3 個:rollbackFor(異常回滾規(guī)則)、isolation(隔離級別)、propagation(傳播機(jī)制)。
3.1 rollbackFor:指定回滾的異常類型
默認(rèn)行為
Spring 事務(wù)默認(rèn)僅對運行時異常(RuntimeException)和 Error 回滾,對非運行時異常(如IOException、SQLException)不回滾。
示例驗證:
@Transactional
@RequestMapping("/r2")
public String r2(String name, String password) throws IOException {
userService.registryUser(name, password);
// 拋出非運行時異常(IOException)
throw new IOException();
}
運行結(jié)果:事務(wù)未回滾,用戶數(shù)據(jù)成功插入數(shù)據(jù)庫。
配置 rollbackFor
若需要對所有異常都回滾,或指定特定異常回滾,通過rollbackFor配置:
// 對所有Exception子類都回滾
@Transactional(rollbackFor = Exception.class)
@RequestMapping("/r2")
public String r2(String name, String password) throws IOException {
userService.registryUser(name, password);
throw new IOException();
}
運行結(jié)果:事務(wù)回滾,用戶數(shù)據(jù)未插入。
擴(kuò)展用法
- 指定多個異常類型:
@Transactional(rollbackFor = {IOException.class, SQLException.class}); - 反向配置(不回滾的異常):
noRollbackFor = XXXException.class(慎用,可能導(dǎo)致數(shù)據(jù)不一致)。
3.2 isolation:事務(wù)隔離級別
事務(wù)隔離級別解決的是 “多個事務(wù)同時操作同一批數(shù)據(jù)時的并發(fā)問題”,主要有三類并發(fā)問題:
- 臟讀:一個事務(wù)讀取到另一個事務(wù)未提交的數(shù)據(jù)(可能回滾,導(dǎo)致讀取的數(shù)據(jù)無效);
- 不可重復(fù)讀:同一事務(wù)內(nèi)多次查詢同一數(shù)據(jù),結(jié)果不一致(其他事務(wù)修改并提交了該數(shù)據(jù));
- 幻讀:同一事務(wù)內(nèi)多次執(zhí)行同一查詢,返回的結(jié)果集行數(shù)不一致(其他事務(wù)新增 / 刪除了數(shù)據(jù))。
3.2.1 MySQL 的四種隔離級別(SQL 標(biāo)準(zhǔn))
MySQL 支持 SQL 標(biāo)準(zhǔn)定義的四種隔離級別,默認(rèn)隔離級別為可重復(fù)讀(REPEATABLE READ):
| 隔離級別 | 臟讀 | 不可重復(fù)讀 | 幻讀 | 說明 |
|---|---|---|---|---|
| 讀未提交(READ UNCOMMITTED) | ? | ? | ? | 最低級別,允許讀取未提交數(shù)據(jù),性能最高但一致性最差 |
| 讀已提交(READ COMMITTED) | ? | ? | ? | 只能讀取已提交數(shù)據(jù),避免臟讀,Oracle 默認(rèn)級別 |
| 可重復(fù)讀(REPEATABLE READ) | ? | ? | ? | 同一事務(wù)內(nèi)多次查詢結(jié)果一致,避免臟讀和不可重復(fù)讀,MySQL 默認(rèn)級別 |
| 串行化(SERIALIZABLE) | ? | ? | ? | 最高級別,事務(wù)串行執(zhí)行,完全避免并發(fā)問題,但性能最差 |
3.2.2 Spring 的五種隔離級別
Spring 在 MySQL 隔離級別的基礎(chǔ)上,增加了DEFAULT(默認(rèn)值),即沿用數(shù)據(jù)庫的隔離級別:
Isolation.DEFAULT:默認(rèn)值,使用數(shù)據(jù)庫的隔離級別(MySQL 為 REPEATABLE READ);Isolation.READ_UNCOMMITTED:對應(yīng) MySQL 的讀未提交;Isolation.READ_COMMITTED:對應(yīng) MySQL 的讀已提交;Isolation.REPEATABLE_READ:對應(yīng) MySQL 的可重復(fù)讀;Isolation.SERIALIZABLE:對應(yīng) MySQL 的串行化。
配置方式
// 設(shè)置隔離級別為讀已提交
@Transactional(isolation = Isolation.READ_COMMITTED)
public void registryUser(String name, String password) {
userInfoMapper.insert(name, password);
}
選擇建議
- 絕大多數(shù)場景:使用默認(rèn)隔離級別(REPEATABLE READ),兼顧一致性和性能;
- 高一致性要求(如金融場景):使用
SERIALIZABLE,但需注意性能損耗; - 低一致性要求(如日志統(tǒng)計):可使用
READ_COMMITTED,提升并發(fā)性能。
3.3 propagation:事務(wù)傳播機(jī)制(核心重點)
當(dāng)多個被@Transactional修飾的方法相互調(diào)用時,事務(wù)如何在方法間傳遞,這就是傳播機(jī)制。比如:方法 A(有事務(wù))調(diào)用方法 B(有事務(wù)),B 是加入 A 的事務(wù),還是新建獨立事務(wù)?
傳播機(jī)制的 7 種行為
Spring 定義了 7 種傳播行為,通過@Transactional(propagation = 傳播行為)配置,核心常用的是前 3 種:
| 傳播行為 | 中文說明 | 核心邏輯 | 通俗比喻(結(jié)婚買房) |
|---|---|---|---|
| REQUIRED(默認(rèn)) | 必須有事務(wù) | 若當(dāng)前存在事務(wù),加入該事務(wù);若不存在,新建事務(wù) | 結(jié)婚必須有房:你有房就一起住,沒房就一起買 |
| REQUIRES_NEW | 新建獨立事務(wù) | 無論當(dāng)前是否有事務(wù),都新建獨立事務(wù),掛起當(dāng)前事務(wù) | 必須買新房:不管你有沒有房,都要重新買一套,各自獨立 |
| NESTED | 嵌套事務(wù) | 若當(dāng)前有事務(wù),創(chuàng)建嵌套事務(wù)(依賴保存點);若不存在,新建事務(wù) | 以房為基礎(chǔ):你有房就用你的房,在房里搞 “小項目”;沒房就一起買 |
| SUPPORTS | 支持事務(wù) | 若當(dāng)前有事務(wù),加入;若沒有,以非事務(wù)方式運行 | 可有可無:你有房就一起住,沒房就租房 |
| MANDATORY | 強(qiáng)制事務(wù) | 若當(dāng)前有事務(wù),加入;若沒有,拋出異常 | 必須有房才結(jié)婚:沒房就不結(jié) |
| NOT_SUPPORTED | 不支持事務(wù) | 以非事務(wù)方式運行,若當(dāng)前有事務(wù),掛起事務(wù) | 不需要房:不管你有沒有房,我都租房住 |
| NEVER | 禁止事務(wù) | 以非事務(wù)方式運行,若當(dāng)前有事務(wù),拋出異常 | 不能有房:你有房就不結(jié)婚 |
四、事務(wù)傳播機(jī)制場景演示:實戰(zhàn)理解核心行為
我們通過 “用戶注冊 + 記錄操作日志” 的場景,演示 3 種核心傳播行為的差異(用戶注冊和記錄日志都是帶事務(wù)的方法)。
準(zhǔn)備工作
- 業(yè)務(wù)邏輯:用戶注冊(
UserService.registryUser)后,記錄操作日志(LogService.insertLog); - 模擬異常:在日志記錄方法中拋出
10/0的運行時異常。
4.1 REQUIRED(默認(rèn)):加入當(dāng)前事務(wù)
代碼配置
// UserService
@Service
public class UserService {
@Autowired
private UserInfoMapper userInfoMapper;
@Transactional(propagation = Propagation.REQUIRED)
public void registryUser(String name, String password) {
userInfoMapper.insert(name, password); // 插入用戶
}
}
// LogService
@Service
public class LogService {
@Autowired
private LogInfoMapper logInfoMapper;
@Transactional(propagation = Propagation.REQUIRED)
public void insertLog(String name, String op) {
int a = 10 / 0; // 模擬異常
logInfoMapper.insertLog(name, op); // 插入日志
}
}
// Controller
@RestController
@RequestMapping("/propaga")
public class PropagationController {
@Autowired
private UserService userService;
@Autowired
private LogService logService;
@Transactional(propagation = Propagation.REQUIRED)
@RequestMapping("/p1")
public String p1(String name, String password) {
userService.registryUser(name, password); // 調(diào)用用戶注冊
logService.insertLog(name, "用戶注冊"); // 調(diào)用日志記錄
return "操作成功";
}
}執(zhí)行結(jié)果
數(shù)據(jù)庫中無用戶數(shù)據(jù)和日志數(shù)據(jù)插入。
流程分析
- Controller 的
p1方法開啟事務(wù); userService.registryUser加入p1的事務(wù),插入用戶數(shù)據(jù)成功;logService.insertLog加入p1的事務(wù),拋出異常;- 由于所有操作在同一個事務(wù)中,異常觸發(fā)整體回滾,用戶數(shù)據(jù)和日志數(shù)據(jù)均回滾。
4.2 REQUIRES_NEW:新建獨立事務(wù)
代碼配置
將兩個 Service 方法的傳播機(jī)制改為REQUIRES_NEW:
// UserService
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void registryUser(String name, String password) {
userInfoMapper.insert(name, password);
}
// LogService
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void insertLog(String name, String op) {
int a = 10 / 0;
logInfoMapper.insertLog(name, op);
}執(zhí)行結(jié)果
數(shù)據(jù)庫中用戶數(shù)據(jù)插入成功,日志數(shù)據(jù)未插入。
流程分析
- Controller 的
p1方法開啟事務(wù); userService.registryUser新建獨立事務(wù),插入用戶數(shù)據(jù)后提交事務(wù)(不受后續(xù)異常影響);logService.insertLog新建獨立事務(wù),拋出異常,該事務(wù)回滾(日志數(shù)據(jù)未插入);- 兩個事務(wù)相互獨立,日志事務(wù)的異常不影響用戶事務(wù)。
4.3 NESTED:嵌套事務(wù)(支持局部回滾)
代碼配置
將兩個 Service 方法的傳播機(jī)制改為NESTED:
// UserService
@Transactional(propagation = Propagation.NESTED)
public void registryUser(String name, String password) {
userInfoMapper.insert(name, password);
}
// LogService
@Transactional(propagation = Propagation.NESTED)
public void insertLog(String name, String op) {
int a = 10 / 0;
logInfoMapper.insertLog(name, op);
}執(zhí)行結(jié)果(未捕獲異常)
數(shù)據(jù)庫中無用戶數(shù)據(jù)和日志數(shù)據(jù)插入。
流程分析
- Controller 的
p1方法開啟事務(wù)(父事務(wù)); userService.registryUser創(chuàng)建嵌套事務(wù)(子事務(wù) 1),插入用戶數(shù)據(jù);logService.insertLog創(chuàng)建嵌套事務(wù)(子事務(wù) 2),拋出異常,子事務(wù) 2 回滾;- 由于子事務(wù) 2 未捕獲異常,異常向上傳播,父事務(wù)回滾,子事務(wù) 1 也隨之回滾。
局部回滾場景(捕獲異常)
修改LogService,捕獲異常并手動回滾當(dāng)前嵌套事務(wù):
@Service
public class LogService {
@Autowired
private LogInfoMapper logInfoMapper;
@Transactional(propagation = Propagation.NESTED)
public void insertLog(String name, String op) {
try {
int a = 10 / 0;
logInfoMapper.insertLog(name, op);
} catch (Exception e) {
e.printStackTrace();
// 手動回滾當(dāng)前嵌套事務(wù)
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
}
}執(zhí)行結(jié)果
數(shù)據(jù)庫中用戶數(shù)據(jù)插入成功,日志數(shù)據(jù)未插入。
核心原理:保存點(Savepoint)
嵌套事務(wù)的局部回滾依賴數(shù)據(jù)庫的保存點(Savepoint) 機(jī)制:
- 父事務(wù)開啟后,每個嵌套事務(wù)執(zhí)行前會創(chuàng)建一個保存點;
- 嵌套事務(wù)回滾時,僅回滾到當(dāng)前保存點,不影響父事務(wù)和其他嵌套事務(wù)的已執(zhí)行操作;
- 父事務(wù)回滾時,會回滾所有嵌套事務(wù)(包括已提交的嵌套事務(wù))。
4.4 NESTED vs REQUIRED:關(guān)鍵區(qū)別
| 對比維度 | REQUIRED | NESTED |
|---|---|---|
| 事務(wù)關(guān)系 | 同一事務(wù) | 父 - 子嵌套事務(wù)(保存點隔離) |
| 回滾范圍 | 要么全回滾,要么全提交 | 支持局部回滾(子事務(wù)回滾不影響父事務(wù)) |
| 異常傳播 | 子事務(wù)異常直接導(dǎo)致整體回滾 | 子事務(wù)異??刹东@,僅回滾當(dāng)前子事務(wù) |
| 適用場景 | 多個操作必須同時成功 / 失?。ㄈ甾D(zhuǎn)賬) | 多個操作可獨立回滾(如注冊 + 送積分,積分失敗不影響注冊) |
五、Spring 事務(wù)常見問題與避坑指南
5.1 @Transactional 注解不生效的場景
- 修飾非 public 方法(如
private、protected); - 異常被
try-catch捕獲且未重新拋出; - 數(shù)據(jù)源未配置事務(wù)管理器(SpringBoot 自動配置,手動配置時需注意);
- 同一個類中無事務(wù)方法調(diào)用有事務(wù)方法(AOP 無法攔截內(nèi)部調(diào)用);
@Service public class UserService { // 無事務(wù)方法 public void test() { registryUser("admin", "123456"); // 內(nèi)部調(diào)用,@Transactional不生效 } @Transactional public void registryUser(String name, String password) { userInfoMapper.insert(name, password); } } - 事務(wù)管理器配置錯誤(如多數(shù)據(jù)源時未指定對應(yīng)事務(wù)管理器)。
5.2 性能優(yōu)化建議
- 避免大事務(wù):事務(wù)范圍越小越好,不要在事務(wù)中執(zhí)行非數(shù)據(jù)庫操作(如調(diào)用第三方接口、文件 IO);
- 合理選擇隔離級別:非核心場景避免使用
SERIALIZABLE,減少鎖競爭; - 傳播機(jī)制按需選擇:無需獨立事務(wù)時用
REQUIRED,需獨立事務(wù)時用REQUIRES_NEW,避免過度使用REQUIRES_NEW導(dǎo)致事務(wù)過多; - 避免長事務(wù):長事務(wù)會占用數(shù)據(jù)庫連接,導(dǎo)致連接池耗盡,影響系統(tǒng)并發(fā)能力。
六、總結(jié)
Spring 事務(wù)是保證數(shù)據(jù)一致性的核心技術(shù),本文從基礎(chǔ)到實戰(zhàn),全面解析了 Spring 事務(wù)的核心知識點:
- 事務(wù)的本質(zhì)是 “原子性操作集合”,解決數(shù)據(jù)一致性問題;
- Spring 事務(wù)有兩種實現(xiàn)方式:編程式(靈活但繁瑣)和聲明式(
@Transactional注解,推薦); @Transactional的三大核心屬性:rollbackFor(控制回滾異常)、isolation(控制并發(fā)問題)、propagation(控制事務(wù)傳播);- 事務(wù)傳播機(jī)制是重點,
REQUIRED(默認(rèn))、REQUIRES_NEW(獨立事務(wù))、NESTED(局部回滾)是高頻使用場景; - 嵌套事務(wù)通過保存點機(jī)制實現(xiàn)局部回滾,適用于 “部分操作可獨立失敗” 的場景。
實際開發(fā)中,建議優(yōu)先使用聲明式事務(wù),根據(jù)業(yè)務(wù)場景靈活配置隔離級別和傳播機(jī)制:
- 轉(zhuǎn)賬、支付等核心場景:用
REQUIRED隔離級別,確保操作原子性; - 注冊 + 日志、下單 + 庫存等場景:用
NESTED或REQUIRES_NEW,實現(xiàn)部分操作獨立回滾; - 非核心查詢場景:用
READ_COMMITTED隔離級別,提升并發(fā)性能。
到此這篇關(guān)于Spring實現(xiàn)方式、隔離級別與傳播機(jī)制全攻略的文章就介紹到這了,更多相關(guān)spring隔離級別與傳播機(jī)制內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot2.7.14整合redis7的詳細(xì)過程
這篇文章主要介紹了SpringBoot2.7.14整合redis7的詳細(xì)過程,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧2023-10-10
SpringBoot定制三種錯誤頁面及錯誤數(shù)據(jù)方法示例
Spring Boot提供的默認(rèn)異常處理機(jī)制通常并不一定適合我們實際的業(yè)務(wù)場景,因此,我們通常會根據(jù)自身的需要對Spring Boot全局異常進(jìn)行統(tǒng)一定制,例如定制錯誤頁面,定制錯誤數(shù)據(jù)等。本文主要介紹了SpringBoot三種自定義錯誤頁面的實現(xiàn),快來學(xué)習(xí)吧2021-12-12
Java?SpringBoot內(nèi)存泄漏問題與解決過程
這篇文章討論了在Java?Spring?Boot應(yīng)用中高并發(fā)場景下遇到的內(nèi)存泄漏問題,通過對日志分析、監(jiān)控工具使用和代碼審查,定位了內(nèi)存泄漏的根本原因,并提出了優(yōu)化代碼和使用監(jiān)控工具的解決方案,最后,通過自動化測試和壓力測試驗證了解決方案的有效性2025-11-11
Java中使用Thread類和Runnable接口實現(xiàn)多線程的區(qū)別
這篇文章主要介紹了使用Thread類和Runnable接口實現(xiàn)多線程的區(qū)別,本文給大家介紹了兩種實現(xiàn)方式的步驟,除了以上兩種多線程實現(xiàn)方式,還可以使用 Callable 接口實現(xiàn),本文通過實例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-07-07
java返回前端樹形結(jié)構(gòu)數(shù)據(jù)的2種實現(xiàn)方式
近期項目有個需求,需要將組織機(jī)構(gòu)數(shù)據(jù)拼成樹型結(jié)構(gòu)返回至前端,下面這篇文章主要給大家介紹了關(guān)于java返回前端樹形結(jié)構(gòu)數(shù)據(jù)的2種實現(xiàn)方式,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-05-05
Spring Boot集成/輸出/日志級別控制/持久化開發(fā)實踐
SpringBoot默認(rèn)集成Logback,支持靈活日志級別配置(INFO/DEBUG等),輸出包含時間戳、級別、類名等信息,并可通過Slf4j注解簡化日志記錄,實現(xiàn)控制臺與文件持久化存儲,本文給大家介紹Spring Boot集成/輸出/日志級別控制/持久化開發(fā)實踐,感興趣的朋友一起看看吧2025-08-08

