java中Spring事務失效的8個常見案例和解決方案
Spring事務管理是企業(yè)級Java應用的核心功能,如果使用不當將會引發(fā)嚴重的生產問題,比如因事務失效帶來的數據不一致問題。事務失效往往不會拋出異常,而是靜默發(fā)生,等到業(yè)務出現問題時才被發(fā)現,造成嚴重的數據不一致。本文將分析8種導致Spring事務失效的使用問題并提供相應的解決方案。
一、事務注解應用在非public方法上
問題現象
開發(fā)者在非public方法上添加@Transactional注解,但事務沒有生效。

Spring AOP的代理機制默認只攔截public方法。
這是因為事務通知是基于Spring AOP實現的,而Spring AOP默認只攔截public方法調用。
查看AbstractFallbackTransactionAttributeSource類的源碼可以發(fā)現:
// AbstractFallbackTransactionAttributeSource.java
protected TransactionAttribute computeTransactionAttribute(Method method, Class<?> targetClass) {
// Don't allow no-public methods as required.
if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
return null;
}
// ...
}非public方法上的@Transactional注解會被直接忽略,返回null,導致事務不生效。
解決方案
確保標注@Transactional的方法為public:

二、同一個類中方法調用
問題現象
在同一個類中,非事務方法調用事務方法,或者事務方法調用另一個具有不同事務屬性的方法,事務會失效。

原理分析

解決方案
有幾種方法可以解決:
方法1:使用自我注入

方法2:使用AopContext獲取代理對象(需要額外配置)

方法3:將方法拆分到不同的類中

三、異常被吞沒
問題現象
開發(fā)者在事務方法中捕獲了異常但沒有重新拋出,導致事務無法回滾。

原理分析

解決方案
有兩種解決方法:
方法1:重新拋出異常

方法2:使用TransactionAspectSupport手動回滾

四、異常類型不匹配回滾規(guī)則
問題現象
開發(fā)者拋出了異常,但事務沒有回滾。
這通常是因為拋出的異常類型不滿足默認的回滾規(guī)則。

原理分析
Spring默認只在遇到未檢查異常(RuntimeException及其子類)和Error時才回滾事務。
受檢異常(如IOException、SQLException)被認為是業(yè)務異常,默認情況下不會觸發(fā)事務回滾。
這是因為@Transactional注解的默認配置是:
@Transactional(rollbackFor = RuntimeException.class)
解決方案
有兩種解決方法:
方法1:指定回滾的異常類型

方法2:將受檢異常轉換為非受檢異常

五、數據庫不支持事務
問題現象
所有事務配置看起來都正確,但事務仍然不生效。
原理分析

解決方案
確保使用支持事務的數據庫引擎:
- 1. 對于MySQL,使用InnoDB引擎而不是MyISAM
- 2. 檢查表的創(chuàng)建語句,確保引擎類型正確:
-- 檢查表引擎 SHOW TABLE STATUS WHERE Name = 'your_table_name'; -- 修改表引擎為InnoDB ALTER TABLE your_table_name ENGINE=InnoDB;
六、錯誤的傳播行為設置
問題現象
在嵌套事務場景中,內部事務的回滾沒有按照預期工作。

原理分析
Spring提供了不同的事務傳播行為,用于控制事務的邊界。
最常用的是:

使用不當的傳播行為會導致事務范圍不符合預期,特別是在異常處理場景中。
解決方案
根據業(yè)務需求選擇正確的傳播行為:

傳播行為選擇指南:

七、未被Spring管理的類
問題現象
在類上添加了@Transactional注解,但事務沒有生效。

原理分析

解決方案
確保類被Spring容器管理:
@Service // 正確:添加@Service注解
public class UserService {
@Autowired
private UserMapper userMapper;
@Transactional
public void createUser(User user) {
userMapper.insert(user);
throw new RuntimeException("測試");
// 現在事務會正常回滾
}
}同時,確保組件掃描配置正確:
@Configuration
@ComponentScan("com.example.service") // 確保包路徑正確
public class AppConfig {
// ...
}八、事務管理器配置錯誤
問題現象
使用了正確的事務注解,但事務不生效或者出現異常。
原理分析
Spring支持多種事務管理器,針對不同的持久化技術:

如果配置了錯誤的事務管理器,或者在多數據源環(huán)境中未指定正確的事務管理器,會導致事務失效。
解決方案
單數據源環(huán)境:確保配置正確的事務管理器

多數據源環(huán)境:指定使用的事務管理器
@Configuration
@EnableTransactionManagement
public class MultiDatabaseConfig {
@Bean
public DataSource primaryDataSource() {
// 主數據源配置...
return new HikariDataSource();
}
@Bean
public DataSource secondaryDataSource() {
// 次數據源配置...
return new HikariDataSource();
}
@Bean
public PlatformTransactionManager primaryTransactionManager() {
return new DataSourceTransactionManager(primaryDataSource());
}
@Bean
public PlatformTransactionManager secondaryTransactionManager() {
return new DataSourceTransactionManager(secondaryDataSource());
}
}
@Service
public class UserService {
// 指定使用的事務管理器
@Transactional(transactionManager = "primaryTransactionManager")
public void createUser(User user) {
// 使用主數據源的操作
}
@Transactional(transactionManager = "secondaryTransactionManager")
public void createUserLog(UserLog log) {
// 使用次數據源的操作
}
}總結
到此這篇關于java中Spring事務失效的8個常見案例和解決方案的文章就介紹到這了,更多相關Spring事務失效的8個常見案例內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
使用Swagger時Controller中api接口顯示不全的問題分析及解決
swagger是一個十分好用的api接口管理、測試框架,現在越來越多的人使用這個做接口的測試和管理,但經常遇到Controller中的api接口顯示不全的問題,所以本文給大家詳細分析了問題以及解決方法,需要的朋友可以參考下2024-02-02
springsecurity實現用戶登錄認證快速使用示例代碼(前后端分離項目)
這篇文章主要介紹了springsecurity實現用戶登錄認證快速使用示例代碼(前后端分離項目),本文通過示例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧2024-03-03
apollo與springboot集成實現動態(tài)刷新配置的教程詳解
這篇文章主要介紹了apollo與springboot集成實現動態(tài)刷新配置,本文分步驟給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-06-06
基于HttpClient在HTTP協議接口測試中的使用(詳解)
下面小編就為大家?guī)硪黄贖ttpClient在HTTP協議接口測試中的使用(詳解)。小編覺得挺不錯的,現在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-10-10
JAVA使用ElasticSearch查詢in和not in的實現方式
今天小編就為大家分享一篇關于JAVA使用Elasticsearch查詢in和not in的實現方式,小編覺得內容挺不錯的,現在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2018-12-12

