Spring事務和事務傳播機制操作大全
一、事務
1.1、什么是事務
事務是一組操作的集合, 是一個不可分割的操作.
事務會把所有的操作作為一個整體, 一起向數據庫提交或者是撤銷操作請求. 所以這組操作要么同時成功,要么同時失敗。
1.2、為什么需要事務
我們在進行程序開發(fā)時, 也會有事務的需求.
比如轉賬操作: 第一步:A 賬戶 -100 元. 第二步:B 賬戶 +100 元. 如果沒有事務,第?步執(zhí)行成功了, 第?步執(zhí)行失敗了, 那么A 賬戶的100 元就平白無故消失了. 如果使 用事務就可以解決這個問題, 讓這?組操作要么?起成功, 要么一起失敗.
比如秒殺系統(tǒng),
第一步: 下單成功
第二步: 扣減庫存
下單成功后, 庫存也需要同步減少. 如果下單成功, 庫存扣減失敗, 那么就會造成下單超出的情況. 所以就需要把這兩步操作放在同一個事務中. 要么一起成功, 要么一起失敗。
1.3、事務的操作
事務的操作主要有三步:
1. 開啟事start transaction/ begin (?組操作前開啟事務)
2. 提交事務: commit (這組操作全部成功, 提交事務)
3. 回滾事務: rollback (這組操作中間任何?個操作出現(xiàn)異常, 回滾事務)
-- 開啟事務 start transaction; -- 提交事務 commit; -- 回滾事務 rollback;
二、Spring中事務的實現(xiàn)
Spring 中的事務操作分為兩類:
- 編程式事務(手動寫代碼操作事務).
- 聲明式事務(利用注解自動開啟和提交事務).
在了解事務之前,我們先準備數據和數據的訪問代碼:
需求: 用戶注冊, 注冊時在日志表中插入?條操作記錄:
數據準備:
-- 創(chuàng)建數據庫 DROP DATABASE IF EXISTS trans_test; CREATE DATABASE trans_test DEFAULT CHARACTER SET utf8mb4; -- ??表 DROP TABLE IF EXISTS user_info; CREATE TABLE user_info ( `id` INT NOT NULL AUTO_INCREMENT, `user_name` VARCHAR (128) NOT NULL, `password` VARCHAR (128) NOT NULL, `create_time` DATETIME DEFAULT now(), `update_time` DATETIME DEFAULT now() ON UPDATE now(), PRIMARY KEY (`id`) ) ENGINE = INNODB DEFAULT CHARACTER SET = utf8mb4 COMMENT = '用戶表'; -- 操作?志表 DROP TABLE IF EXISTS log_info; CREATE TABLE log_info ( `id` INT PRIMARY KEY auto_increment, `user_name` VARCHAR ( 128 ) NOT NULL, `op` VARCHAR ( 256 ) NOT NULL, `create_time` DATETIME DEFAULT now(), `update_time` DATETIME DEFAULT now() ON UPDATE now() ) DEFAULT charset 'utf8mb4';
代碼準備:
1.創(chuàng)建項目 spring-trans, 引?Spring Web, Mybatis, mysql等依賴
2 . 配置文件:
spring: datasource: url: jdbc:mysql://127.0.0.1:3306/trans_testcharacterEncoding=utf8&useSSL=false username: root password: root driver-class-name: com.mysql.cj.jdbc.Driver mybatis: configuration: # 配置打印 MyBatis?志 log-impl: org.apache.ibatis.logging.stdout.StdOutImpl map-underscore-to-camel-case: true #配置駝峰?動轉換
3.實體類
@Data
public class UserInfo {
private Integer id;
private String userName;
private String password;
private Date createTime;
private Date updateTime;
}
@Data
public class LogInfo {
private Integer id;
private String userName;
private String op;
private Date createTime;
private Date updateTime;
}
4.Mapper
@Mapper
public interface UserInfoMapper {
@Insert("insert into user_info(`user_name`,`password`)values(#{name},#
{password})")
Integer insert(String name, String password);
}
@Mapper
public interface LogInfoMapper {
@Insert("insert into log_info(`user_name`,`op`)values(#{name},#{op})")
Integer insertLog(String name, String op);
}5.Service
@Slf4j
@Service
public class UserService {
@Autowired
private UserInfoMapper userInfoMapper;
public void registryUser(String name, String password) {
//插???信息
userInfoMapper.insert(name, password);
}
}
@Slf4j
@Service
public class LogService {
@Autowired
private LogInfoMapper logInfoMapper;
public void insertLog(String name, String op) {
//記錄??操作
logInfoMapper.insertLog(name, "?戶注冊");
}
}6.Controller
@RequestMapping("/user")
@RestController
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/registry")
public String registry(String name, String password) {
//??注冊
userService.registryUser(name, password);
return "注冊成功";
}
}2.1、Spring編程式事務
Spring 手動操作事務和上面 MySQL 操作事務類似, 有 3 個重要操作步驟:
• 開啟事務(獲取事務)
• 提交事務
• 回滾事務
SpringBoot 內置了兩個對象:
- DataSourceTransactionManager 事務管理器. 用來獲取事務(開啟事務), 提交或回滾事務的
- TransactionDefinition 是事務的屬性, 在獲取事務的時候需要將TransactionDefinition 傳遞進去從?獲得?個事務 TransactionStatus。
我們還是根據代碼的實現(xiàn)來學習:
@RequestMapping("/user")
@RestController
public class UserController {
// JDBC 事務管理器
@Autowired
private DataSourceTransactionManager dataSourceTransactionManager;
// 定義事務屬性
@Autowired
private TransactionDefinition transactionDefinition;
@Autowired
private UserService userService;
@RequestMapping("/registry")
public String registry(String name, String password) {
// 開啟事務
TransactionStatus transactionStatus = dataSourceTransactionManager
.getTransaction(transactionDefinition);
//??注冊
userService.registryUser(name, password);
//提交事務
dataSourceTransactionManager.commit(transactionStatus);
//回滾事務
//dataSourceTransactionManager.rollback(transactionStatus);
return "注冊成功";
}
}運?程序之后,用postman測試接口,觀看數據庫結果數據插入成功。

觀察事務回滾:
//回滾事務 dataSourceTransactionManager.rollback(transactionStatus);
觀察數據庫, 雖然程序返回"注冊成功", 但數據庫并沒有新增數據.
以上代碼雖然可以實現(xiàn)事務, 但操作也很繁瑣, 有沒有更簡單的實現(xiàn)?法呢? 接下來我們學習聲明式事務。
2.2、Spring 聲明式事務 @Transactional
聲明式事務的實現(xiàn)很簡單, 只需要在需要事務的放法上添加 @Transactional 注解就可以實現(xiàn)了. 無需手動開啟事務和提交事務, 進入方法時自動開啟事務, 方法執(zhí)行完會自動提交事務, 如果中途發(fā)生了 沒有處理的異常會自動回滾事務.
我們來看代碼實現(xiàn):
@RequestMapping("/trans")
@RestController
public class TransactionalController {
@Autowired
private UserService userService;
@Transactional
@RequestMapping("/registry")
public String registry(String name, String password) {
//??注冊
userService.registryUser(name, password);
return "注冊成功";
}
}運?程序, 發(fā)現(xiàn)數據插?成功.
修改程序, 使之出現(xiàn)異常
@Slf4j
@RequestMapping("/trans")
@RestController
public class TransactionalController {
@Autowired
private UserService userService;
@Transactional
@RequestMapping("/registry")
public String registry(String name, String password) {
//??注冊
userService.registryUser(name, password);
log.info("??數據插?成功");
//強制程序拋出異常
int a = 10 / 0;
return "注冊成功";
}
}運行程序: 發(fā)現(xiàn)雖然日志顯示數據插?成功, 但數據庫卻沒有新增數據, 事務進行了回滾.

@Transactional 作?
@Transactional 可以用來修飾方法或類:
• 修飾方法時: 只有修飾public方法時才生效(修飾其他方法時不會報錯, 也不生效)
• 修飾類時: 對 @Transactional 修飾的類中所有的 public 方法都生效
方法/類被 @Transactional 注解修飾時, 在目標方法執(zhí)行開始之前, 會?動開啟事務, ?法執(zhí)行結束 之后, 自動提交事務.
如果在方法執(zhí)行過程中, 出現(xiàn)異常, 且異常未被捕獲, 就進行事務回滾操作.
如果異常被程序捕獲, 方法就被認為是成功執(zhí)行, 依然會提交事務.
修改上述代碼, 對異常進?捕獲:
@Transactional
@RequestMapping("/registry")
public String registry(String name, String password) {
//??注冊
userService.registryUser(name, password);
log.info("??數據插?成功");
//對異常進?捕獲
try {
//強制程序拋出異常
int a = 10 / 0;
} catch (Exception e) {
e.printStackTrace();
}
return "注冊成功";
}運?程序, 發(fā)現(xiàn)雖然程序出錯了, 但是由于異常被捕獲了, 所以事務依然得到了提交. 如果需要事務進?回滾, 有以下兩種方式:
- 重新拋出異常
@Transactional
@RequestMapping("/registry")
public String registry(String name, String password) {
//??注冊
userService.registryUser(name, password);
log.info("??數據插?成功");
//對異常進?捕獲
try {
//強制程序拋出異常
int a = 10 / 0;
} catch (Exception e) {
//將異常重新拋出去
throw e;
}
return "注冊成功";
}- 手動回滾事務
使用 TransactionAspectSupport.currentTransactionStatus() 得到當前的事務, 并 使? setRollbackOnly 設置 setRollbackOnly。
@Transactional
@RequestMapping("/registry")
public String registry(String name, String password) {
//??注冊
userService.registryUser(name, password);
log.info("??數據插?成功");
//對異常進?捕獲
try {
//強制程序拋出異常
int a = 10 / 0;
} catch (Exception e) {
// ?動回滾事務
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
return "注冊成功";
}三、@Transactional 詳解
通過上面的代碼, 我們學習了 @Transactional 的基本使用. 接下來我們學習 @Transactional
注解的使用細節(jié). 我們主要學習 @Transactional 注解當中的三個常見屬性:
- rollbackFor: 異?;貪L屬性. 指定能夠觸發(fā)事務回滾的異常類型. 可以指定多個異常類型
- Isolation: 事務的隔離級別. 默認值為 Isolation.DEFAULT
- propagation: 事務的傳播機制. 默認值為 Propagation.REQUIRED
3.1、rollbackFor
@Transactional 默認只在遇到運行時異常和Error時才會回滾, 非運行時異常不回滾. 即Exception的子類中, 除了RuntimeException及其子類。
如果我們需要所有異常都回滾, 需要來配置 @Transactional 注解當中的 rollbackFor 屬性, 通過 rollbackFor 這個屬性指定出現(xiàn)何種異常類型時事務進行回滾。
@Transactional(rollbackFor = Exception.class)
@RequestMapping("/r2")
public String r2(String name, String password) throws IOException {
//??注冊
userService.registryUser(name, password);
log.info("??數據插?成功");
if (true) {
throw new IOException();
}
return "r2";
}
運行程序后,發(fā)現(xiàn)雖然程序拋出了異常, 但是事務依然進?了提交.
結論:
• 在Spring的事務管理中,默認只在遇到運行時異常RuntimeException和Error時才會回滾.
• 如果需要回滾指定類型的異常, 可以通過rollbackFor屬性來指定.
3.2事務隔離級別
3.2.1、MySQL 事務隔離級別
SQL 標準定義了四種隔離級別, MySQL 全都?持. 這四種隔離級別分別是:
- 讀未提交(READ UNCOMMITTED): 讀未提交, 也叫未提交讀. 該隔離級別的事務可以看到其他事務中 未提交的數據. 因為其他事務未提交的數據可能會發(fā)生回滾, 但是該隔離級別卻可以讀到, 我們把該級別讀到的數 據稱之為臟數據, 這個問題稱之為臟讀.
2 . 讀提交(READ COMMITTED): 讀已提交, 也叫提交讀. 該隔離級別的事務能讀取到已經提交事務的數 據,該隔離級別不會有臟讀的問題.但由于在事務的執(zhí)?中可以讀取到其他事務提交的結果, 所以在不 同時間的相同 SQL 查詢可能會得到不同的結果, 這種現(xiàn)象叫做不可重復讀
3 . 可重復讀(REPEATABLE READ): 事務不會讀到其他事務對已有數據的修改, 即使其他事務已提交. 也 就可以確保同?事務多次查詢的結果?致, 但是其他事務新插?的數據, 是可以感知到的. 這也就引 發(fā)了幻讀問題. 可重復讀, 是 MySQL 的默認事務隔離級別. 比如此級別的事務正在執(zhí)行時, 另?個事務成功的插?了某條數據, 但因為它每次查詢的結果都是?樣的, 所以會導致查詢不到這條數據, 自己重復插入時又失敗(因為唯?約束的原因). 明明在事務中查詢不到這條信息,但自己就是插入不進去, 這個現(xiàn)象叫幻讀.
4 . 串行化(SERIALIZABLE): 序列化, 事務最高隔離級別. 它會強制事務排序, 使之不會發(fā)生沖突, 從而解決了臟讀, 不可重復讀和幻讀問題, 但因為執(zhí)行效率低, 所以真正使用的場景并不多.
3.2.2、Spring 事務隔離級別
Spring 中事務隔離級別有5 種:
- Isolation.DEFAULT : 以連接的數據庫的事務隔離級別為主.
2 . Isolation.READ_UNCOMMITTED : 讀未提交, 對應SQL標準中 READ UNCOMMITTED
3 . Isolation.READ_COMMITTED : 讀已提交,對應SQL標準中 READ COMMITTED
4 . Isolation.REPEATABLE_READ : 可重復讀, 對應SQL標準中 REPEATABLE READ
5 . Isolation.SERIALIZABLE : 串?化, 對應SQL標準中 SERIALIZABLE
public enum Isolation {
DEFAULT(-1),
READ_UNCOMMITTED(1),
READ_COMMITTED(2),
REPEATABLE_READ(4),
SERIALIZABLE(8);
private final int value;
private Isolation(int value) {
this.value = value;
}
public int value() {
return this.value;
}
}
Spring 中事務隔離級別可以通過 @Transactional 中的 isolation 屬性進行設置。
@Transactional(isolation = Isolation.READ_COMMITTED)
@RequestMapping("/r3")
public String r3(String name,String password) throws IOException {
//... 代碼省略
return "r3";
}
3.3、Spring 事務傳播機制
3.3.1、什么是事務傳播機制?
事務傳播機制就是: 多個事務方法存在調用關系時, 事務是如何在這些方法間進行傳播的?
比如有兩個方法A, B都被 @Transactional 修飾, A方法調用B方法 A方法運行時, 會開啟?個事務. 當A調用B時, B方法本身也有事務, 此時B方法運行時, 是加入A的事務, 還 是創(chuàng)建一個新的事務呢? 這個就涉及到了事務的傳播機制。
比如公司流程管理
執(zhí)行任務之前, 需要先寫執(zhí)行?檔, 任務執(zhí)行結束, 再寫總結匯報

此時A部門有?項工作, 需要B部門的支援, 此時B部門是直接使用A部門的?檔, 還是新建一個文檔呢?
事務隔離級別解決的是多個事務同時調用一個數據庫的問題:

而事務傳播機制解決的是?個事務在多個節(jié)點(?法)中傳遞的問題:
3.3.2、事務的傳播機制有哪些
@Transactional 注解支持事務傳播機制的設置, 通過 propagation 屬性來指定傳播?為.Spring 事務傳播機制有以下 7 種:
- Propagation.REQUIRED : 默認的事務傳播級別. 如果當前存在事務, 則加入該事務. 如果當前沒有事務, 則創(chuàng)建一個新的事務.
2 . Propagation.SUPPORTS : 如果當前存在事務, 則加入該事務. 如果當前沒有事務, 則以非事務的方式繼續(xù)運行.
3 . Propagation.MANDATORY :強制性. 如果當前存在事務, 則加?該事務. 如果當前沒有事務, 則 拋出異常.
4 . Propagation.REQUIRES_NEW : 創(chuàng)建?個新的事務. 如果當前存在事務, 則把當前事務掛起. 也 就是說不管外部?法是否開啟事務, Propagation.REQUIRES_NEW 修飾的內部方法都會新開 啟??的事務, 且開啟的事務相互獨立, 互不干擾.
5 . Propagation.NOT_SUPPORTED : 以非事務方式運行, 如果當前存在事務, 則把當前事務掛起(不用).
6 . Propagation.NEVER : 以非事務方式運行, 如果當前存在事務, 則拋出異常.
7 . Propagation.NESTED : 如果當前存在事務, 則創(chuàng)建?個事務作為當前事務的嵌套事務來運行. 如果當前沒有事務, 則該取值等價于 PROPAGATION_REQUIRED .
public enum Propagation {
REQUIRED(0),
SUPPORTS(1),
MANDATORY(2),
REQUIRES_NEW(3),
NOT_SUPPORTED(4),
NEVER(5),
NESTED(6);
private final int value;
private Propagation(int value) {
this.value = value;
}
public int value() {
return this.value;
}
}3.3.3、Spring 事務傳播機制使用和各種場景演示
對于以上事務傳播機制,我們重點關注以下兩個就可以了:
- REQUIRED(默認值)
- REQUIRES_NEW
3.3.3.1 REQUIRED(加入事務)
看下?代碼實現(xiàn):
- 用戶注冊, 插入一條數據
- 記錄操作日志, 插入一條數據(出現(xiàn)異常)
觀察 propagation = Propagation.REQUIRED 的執(zhí)行結果:
@RequestMapping("/propaga")
@RestController
public class PropagationController {
@Autowired
private UserService userService;
@Autowired
private LogService logService;
@Transactional(propagation = Propagation.REQUIRED)
@RequestMapping("/p1")
public String r3(String name, String password) {
//??注冊
userService.registryUser(name, password);
//記錄操作?志
logService.insertLog(name, "??注冊");
return "r3";
}
}對應的UserService和LogService都添加上 @Transactional(propagation =
Propagation.REQUIRED)。
@Slf4j
@Service
public class UserService {
@Autowired
private UserInfoMapper userInfoMapper;
@Transactional(propagation = Propagation.REQUIRED)
public void registryUser(String name, String password) {
//插???信息
userInfoMapper.insert(name, password);
}
}
@Slf4j
@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, "??注冊");
}
}運行程序, 發(fā)現(xiàn)數據庫沒有插入任何數據. 流程描述:
- p1 方法開始事務
- 用戶注冊, 插入一條數據 (執(zhí)行成功) (和p1 使用同?個事務)
- 記錄操作日志, 插入一條數據(出現(xiàn)異常, 執(zhí)行失敗) (和p1 使用同?個事務)
- 因為步驟3出現(xiàn)異常, 事務回滾. 步驟2和3使用同?個事務, 所以步驟2的數據也回滾了.
3.3.3.2、REQUIRES_NEW(新建事務)
將上述UserService 和LogService 中相關?法事務傳播機制改為Propagation.REQUIRES_NEW。
@Service
public class UserService {
@Autowired
private UserInfoMapper userInfoMapper;
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void registryUser(String name, String password) {
//插???信息
userInfoMapper.insert(name, password);
}
}
@Service
public class LogService {
@Autowired
private LogInfoMapper logInfoMapper;
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void insertLog(String name, String op) {
int a = 10 / 0;
//記錄??操作
logInfoMapper.insertLog(name, "??注冊");
}
}運行程序, 發(fā)現(xiàn)用戶數據插入成功了, 日志表數據插入失敗.
LogService 方法中的事務不影響 UserService 中的事務.
當我們不希望事務之間相互影響時, 可以使用該傳播行為.
3.3.3、NEVER (不支持當前事務, 拋異常)
修改UserService 中對應?法的事務傳播機制為 Propagation.NEVER
@Slf4j
@Service
public class UserService {
@Autowired
private UserInfoMapper userInfoMapper;
@Transactional(propagation = Propagation.NEVER)
public void registryUser(String name, String password) {
//插???信息
userInfoMapper.insert(name, password);
}
}程序執(zhí)行報錯, 沒有數據插入.
3.3.3.4、NESTED(嵌套事務)
將上述UserService 和LogService 中相關方法事務傳播機制改為 Propagation.NESTED。
@Slf4j
@Service
public class UserService {
@Autowired
private UserInfoMapper userInfoMapper;
@Transactional(propagation = Propagation.NESTED)
public void registryUser(String name, String password) {
//插???信息
userInfoMapper.insert(name, password);
}
}
@Slf4j
@Service
public class LogService {
@Autowired
private LogInfoMapper logInfoMapper;
@Transactional(propagation = Propagation.NESTED)
public void insertLog(String name, String op) {
int a = 10 / 0;
//記錄??操作
logInfoMapper.insertLog(name, "??注冊");
}
}運?程序, 發(fā)現(xiàn)沒有任何數據插入. 流程描述:
- Controller 中p1 方法開始事務
- UserService 用戶注冊, 插入一條數據 (嵌套p1事務)
- LogService 記錄操作日志, 插入一條數據(出現(xiàn)異常, 執(zhí)行失敗) (嵌套p1事務, 回滾當前事務, 數據添加失敗)
- 由于是嵌套事務, LogService 出現(xiàn)異常之后, 往上找調用它的方法和事務, 所以用戶注冊也失敗了.
- 最終結果是兩個數據都沒有添加
p1事務可以認為是父事務, 嵌套事務是子事務. 父事務出現(xiàn)異常, 子事務也會回滾, 子事務出現(xiàn)異常, 如果不進行處理, 也會導致父事務回滾.
3.3.3.5 NESTED和REQUIRED 有什么區(qū)別?
我們在 LogService 進?當前事務回滾, 修改 LogService 代碼如下:
@Service
public class LogService {
@Autowired
private LogInfoMapper logInfoMapper;
@Transactional(propagation = Propagation.NESTED)
public void insertLog(String name, String op) {
try {
int a = 10 / 0;
} catch (Exception e) {
//回滾當前事務
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
//記錄??操作
logInfoMapper.insertLog(name, "??注冊");
}
}重新運行程序, 發(fā)現(xiàn)用戶表數據添加成功, 日志表添加失敗.
LogService 中的事務已經回滾, 但是嵌套事務不會回滾嵌套之前的事務, 也就是說嵌套事務可以實現(xiàn)部分事務回滾。
對?REQUIRED
把 NESTED 傳播機制改為 REQUIRED, 修改代碼如下:
@Service
public class UserService {
@Autowired
private UserInfoMapper userInfoMapper;
@Transactional(propagation = Propagation.REQUIRED)
public void registryUser(String name, String password) {
//插???信息
userInfoMapper.insert(name, password);
}
}
@Service
public class LogService {
@Autowired
private LogInfoMapper logInfoMapper;
@Transactional(propagation = Propagation.REQUIRED)
public void insertLog(String name, String op) {
try {
int a = 10 / 0;
} catch (Exception e) {
//回滾當前事務
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
//記錄??操作
logInfoMapper.insertLog(name, "??注冊");
}
}重新運行程序, 發(fā)現(xiàn)用戶表和日志表的數據添加都失敗了.
REQUIRED 如果回滾就是回滾所有事務, 不能實現(xiàn)部分事務的回滾. (因為屬于同?個事務)
NESTED和REQUIRED區(qū)別:
• 整個事務如果全部執(zhí)行成功, ?者的結果是?樣的.
• 如果事務?部分執(zhí)行成功, REQUIRED加入事務會導致整個事務全部回滾. NESTED嵌套事務可以實現(xiàn)局部回滾, 不會影響上一個方法中執(zhí)行的結果.
嵌套事務之所以能夠實現(xiàn)部分事務的回滾, 是因為事務中有?個保存點(savepoint)的概念, 嵌套事務 進入之后相當于新建了?個保存點, 而滾回時只回滾到當前保存點。
REQUIRED 是加入到當前事務中, 并沒有創(chuàng)建事務的保存點, 因此出現(xiàn)了回滾就是整個事務回滾, 這就是嵌套事務和加入事務的區(qū)別
總結
- Spring中使用事務, 有兩種方式: 編程式事務(手動操作)和聲明式事務. 其中聲明式事務使用較多,在方法上添加 @Transactional 就可以實現(xiàn)了
- 通過 @Transactional(isolation = Isolation.SERIALIZABLE) 設置事務的隔離級別. Spring 中的事務隔離級別有 5 種
- 通過 @Transactional(propagation = Propagation.REQUIRED) 設置事務的傳播機制, Spring 中的 事務傳播級別有 7 種, 重點關注 REQUIRED (默認值) 和 REQUIRES_NEW
以上就是本文全部內容,感謝各位能夠看到最后,如有問題,歡迎各位大佬在評論區(qū)指正,希望大家可以有所收獲!創(chuàng)作不易,希望大家多多支持!
到此這篇關于Spring事務和事務傳播機制操作大全的文章就介紹到這了,更多相關spring事務傳播機制內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
SpringBoot實現(xiàn)Tomcat集群的會話管理功能
在使用 Tomcat 集群時,由于每個 Tomcat 實例的 Session 存儲是獨立的,導致無法實現(xiàn) Session 的共享,這可能影響到用戶跨節(jié)點的訪問,為了實現(xiàn)跨 Tomcat 實例共享 Session,可以使用 Spring Session 配合 Redis 進行集中式會話管理,需要的朋友可以參考下2024-12-12
springboot整合企微webhook機器人發(fā)送消息提醒
這篇文章主要為大家介紹了springboot整合企微webhook機器人發(fā)送消息提醒,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-12-12
SpringBoot使用Redis進行限流功能實現(xiàn)
Spring Boot中使用Redis實現(xiàn)限流功能是一種常見的做法,特別是在高并發(fā)場景下,限流可以有效防止系統(tǒng)過載,保證服務的穩(wěn)定性,本文就來詳細的介紹一下SpringBoot使用Redis進行限流功能實現(xiàn),感興趣的可以了解一下2025-10-10
java接收文件流+response.body()調用兩次問題(分別接收文件和對象)
這篇文章主要介紹了java接收文件流+response.body()調用兩次問題(分別接收文件和對象),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-06-06
springboot使用EMQX(MQTT協(xié)議)的實現(xiàn)
最近由于iot越來越火, 物聯(lián)網的需求越來越多, 那么理所當然的使用mqtt的場景也就越來越多,本文主要介紹了springboot使用EMQX(MQTT協(xié)議)的實現(xiàn),感興趣的可以了解一下2023-10-10

