網站首頁 編程語言 正文
Spring 事務失效指在使用 Spring 進行事務管理時,事務沒有被正確地提交或回滾所致的問題。可能是因為代碼中未正確地配置事務管理器或者事務注解的使用不正確所導致的。如果事務失效,則數據庫操作可能未能正確地更新或回滾,可能會造成不可預知的結果,從而影響系統的穩定性和一致性。
1. 訪問權限問題
Java 的訪問權限有4種:private
、default
、protected
、public
,它們的權限從左到右,以此變大。如果在開發中,將事務方法定義了錯誤的訪問權限,則事務功能會失效。
@Service
public class EmpService {
@Transactional
private void add(UserModel userModel){
saveData(userModel);
}
}
如上:add 方法的權限被定義成了?private
,這樣會導致事務失效,Spring 要求被代理方法必須是public
的。
在Spring源碼中,如果目標方法不是?
public
,則?TransactionAttribute?
返回 null,不支持事務。
2. 方法被 final 修飾
方法被final
修飾時,也會導致事務失效,如下的add方法使用了final
修飾,造成事務失效。
@Service
public class EmpService {
@Transactional
public final void add(UserModel userModel){
saveData(userModel);
}
}
因為 Spring 事務底層是用了 AOP ,用了JDK的動態代理或者CGLB的動態代理,會幫我們生成代理類,在代理類中實現事務功能。如果某個方法被final修飾了,那么在代理類中,就無法重新該方法,而添加事務功能。
注意:如果某個方法被static修飾,同樣也無法通過動態代理,變成事務方法。
3. 直接調用內部方法
@Service
public class EmpService {
public void add(UserModel userModel){
saveData(userModel);
updateSataus(userModel);
}
@Transactional
public void updateSataus(UserModel userModel){
doSomething();
}
}
在事務方法add可知,它直接調用了 updateStatus 方法,方法擁有事務的能力是因為 Spring AOP 中生成了代理對象,但是直接調用 updateStatus 方法不會直接生成事務。但是可以直接將該類直接注入進來,比如:
@Service
public class EmpService {
private EmpService empService;
@Transactional
public void add(UserModel userModel){
saveData(userModel);
empService.updateSataus(userModel);
}
@Transactional(rollbackFor = Exception.class)
public void updateSataus(UserModel userModel){
doSomething();
}
}
這樣事務就生效了,也不會穿生循環依賴的問題。
4. 未被 Spring 管理
如下所示:EmpService 類沒有交給 Spring 進行管理(沒添加@Service
等注解),導致事務失效。
public class EmpService {
@Transactional
public void add(UserModel userModel){
saveData(userModel);
updateSataus(userModel);
}
}
5. 多線程調用
由以下代碼可知:在 add 事務方法里面,調用了 updateStatus 事務方法,但是 updateStatus 事務方法是在另外一個線程中調用的。這樣就導致了兩個方法不在同一個線程中,獲取到了數據庫連接不一樣,從而是兩個不同的事務,如果 updateStatus 方法中拋出了異常,add 方法是不會回滾的。
@Service
public class EmpService {
@Autowired
private OrderService orderService;
@Transactional
public void add(UserModel userModel){
new Thread(()->{
orderService.updateSataus();
}).start();
}
}
@Service
public class OrderService{
@Transactional
public void updateSataus(){
System.out.println("======================");
}
}
Spring的事務是通過數據庫的連接來實現的:
當前線程中保存了一個 map,key 是數據源,value 是數據庫連接。同一個事務,指同一個數據庫連接,只有擁有同一個事務連接才能保證同時提交和回滾。如果是不同的線程,拿到的數據庫連接肯定是不同的。
6. 數據庫不支持事務
如果數據庫的引擎是myisam
,那么它是不支持事務的,要想支持事務,改成innodb
引擎
7. 事務沒有開啟
如果是 Spring Boot 項目,那么是事務默認是開啟的,但如果是 Spring 項目,需要 xml 配置
8. 事務的傳播特性
如果事務的傳播特性設置錯了,事務也會失效
如下:Propagation.NEVER
這種類型的傳播特性不支持事務,如果有事務會拋出異常。
@Service
public class EmpService {
//Propagation.NEVER傳播特性不支持事務
@Transactional(propagation = Propagation.NEVER)
public void add(UserModel userModel){
saveData(userModel);
updateSataus(userModel);
}
}
目前只有這三種傳播特性才會創建新事物:REQUIRED
、REQUIRES_NEW
、NESTED
9. 自己捕獲了異常
事務不會回滾,最常見的問題是:開發者在代碼中手動try...catch了異常
@Service
public class EmpService {
@Transactional
public void add(UserModel userModel){
try {//開發者手動捕獲了異常,導致事務失效
saveData(userModel);
updateSataus(userModel);
} catch (Exception e) {
e.printStackTrace();
}
}
}
10. 手動拋了別的異常
如果拋的異常不正確,事務也不會回滾
@Service
public class EmpService {
@Transactional
public void add(UserModel userModel) throws Exception {
try {
saveData(userModel);
updateSataus(userModel);
} catch (Exception e) {
throw new Exception(e);
}
}
}
因為 Spring 事務,默認情況下只會回滾RuntimeException(運行時異常)
和Error(錯誤)
,對于普通的非運行時異常,它不會回滾。
11. 自定義回滾異常
如果在使用@Transactional
注解聲明事務時,有時想自定義回滾異常,Spring 也是支持的。可以通過設置rollbackFor
參數,來完成這個功能。如下:
@Service
public class EmpService {
@Transactional(rollbackFor = BusinessException.class)
public void add(UserModel userModel) {
saveData(userModel);
updateSataus(userModel);
}
}
但是如果在程序執行過程中,出現了 SQL 異常,但是 SQL 異常并不屬于我們定義的 BusinessException
異常,所以事務也不會回滾
原文鏈接:https://blog.csdn.net/Mr_VK/article/details/136438383
- 上一篇:沒有了
- 下一篇:沒有了
相關推薦
- 2022-08-15 前端寫代碼的時候,不滿足條件程序停止執行下面的程序,并彈窗提示
- 2023-02-04 C#實現利用Linq操作Xml文件_C#教程
- 2022-02-03 checkbox修改默認樣式
- 2022-10-02 Pandas中的unique()和nunique()區別詳解_python
- 2023-02-25 C++命名空間using?namespace?std是什么意思_C 語言
- 2022-10-31 一篇文章教會你使用gs_restore導入數據_數據庫其它
- 2023-02-27 Golang設計模式中抽象工廠模式詳細講解_Golang
- 2023-04-07 React?Fiber構建completeWork源碼解析_React
- 欄目分類
-
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支