java中Spring事務(wù)失效的8個常見案例和解決方案
Spring事務(wù)管理是企業(yè)級Java應(yīng)用的核心功能,如果使用不當將會引發(fā)嚴重的生產(chǎn)問題,比如因事務(wù)失效帶來的數(shù)據(jù)不一致問題。事務(wù)失效往往不會拋出異常,而是靜默發(fā)生,等到業(yè)務(wù)出現(xiàn)問題時才被發(fā)現(xiàn),造成嚴重的數(shù)據(jù)不一致。本文將分析8種導(dǎo)致Spring事務(wù)失效的使用問題并提供相應(yīng)的解決方案。
一、事務(wù)注解應(yīng)用在非public方法上
問題現(xiàn)象
開發(fā)者在非public方法上添加@Transactional
注解,但事務(wù)沒有生效。
Spring AOP的代理機制默認只攔截public方法。
這是因為事務(wù)通知是基于Spring AOP實現(xiàn)的,而Spring AOP默認只攔截public方法調(diào)用。
查看AbstractFallbackTransactionAttributeSource
類的源碼可以發(fā)現(xiàn):
// 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,導(dǎo)致事務(wù)不生效。
解決方案
確保標注@Transactional
的方法為public:
二、同一個類中方法調(diào)用
問題現(xiàn)象
在同一個類中,非事務(wù)方法調(diào)用事務(wù)方法,或者事務(wù)方法調(diào)用另一個具有不同事務(wù)屬性的方法,事務(wù)會失效。
原理分析
解決方案
有幾種方法可以解決:
方法1:使用自我注入
方法2:使用AopContext獲取代理對象(需要額外配置)
方法3:將方法拆分到不同的類中
三、異常被吞沒
問題現(xiàn)象
開發(fā)者在事務(wù)方法中捕獲了異常但沒有重新拋出,導(dǎo)致事務(wù)無法回滾。
原理分析
解決方案
有兩種解決方法:
方法1:重新拋出異常
方法2:使用TransactionAspectSupport手動回滾
四、異常類型不匹配回滾規(guī)則
問題現(xiàn)象
開發(fā)者拋出了異常,但事務(wù)沒有回滾。
這通常是因為拋出的異常類型不滿足默認的回滾規(guī)則。
原理分析
Spring默認只在遇到未檢查異常(RuntimeException及其子類)和Error時才回滾事務(wù)。
受檢異常(如IOException、SQLException)被認為是業(yè)務(wù)異常,默認情況下不會觸發(fā)事務(wù)回滾。
這是因為@Transactional
注解的默認配置是:
@Transactional(rollbackFor = RuntimeException.class)
解決方案
有兩種解決方法:
方法1:指定回滾的異常類型
方法2:將受檢異常轉(zhuǎn)換為非受檢異常
五、數(shù)據(jù)庫不支持事務(wù)
問題現(xiàn)象
所有事務(wù)配置看起來都正確,但事務(wù)仍然不生效。
原理分析
解決方案
確保使用支持事務(wù)的數(shù)據(jù)庫引擎:
- 1. 對于MySQL,使用InnoDB引擎而不是MyISAM
- 2. 檢查表的創(chuàng)建語句,確保引擎類型正確:
-- 檢查表引擎 SHOW TABLE STATUS WHERE Name = 'your_table_name'; -- 修改表引擎為InnoDB ALTER TABLE your_table_name ENGINE=InnoDB;
六、錯誤的傳播行為設(shè)置
問題現(xiàn)象
在嵌套事務(wù)場景中,內(nèi)部事務(wù)的回滾沒有按照預(yù)期工作。
原理分析
Spring提供了不同的事務(wù)傳播行為,用于控制事務(wù)的邊界。
最常用的是:
使用不當?shù)膫鞑バ袨闀?dǎo)致事務(wù)范圍不符合預(yù)期,特別是在異常處理場景中。
解決方案
根據(jù)業(yè)務(wù)需求選擇正確的傳播行為:
傳播行為選擇指南:
七、未被Spring管理的類
問題現(xiàn)象
在類上添加了@Transactional
注解,但事務(wù)沒有生效。
原理分析
解決方案
確保類被Spring容器管理:
@Service // 正確:添加@Service注解 public class UserService { @Autowired private UserMapper userMapper; @Transactional public void createUser(User user) { userMapper.insert(user); throw new RuntimeException("測試"); // 現(xiàn)在事務(wù)會正常回滾 } }
同時,確保組件掃描配置正確:
@Configuration @ComponentScan("com.example.service") // 確保包路徑正確 public class AppConfig { // ... }
八、事務(wù)管理器配置錯誤
問題現(xiàn)象
使用了正確的事務(wù)注解,但事務(wù)不生效或者出現(xiàn)異常。
原理分析
Spring支持多種事務(wù)管理器,針對不同的持久化技術(shù):
如果配置了錯誤的事務(wù)管理器,或者在多數(shù)據(jù)源環(huán)境中未指定正確的事務(wù)管理器,會導(dǎo)致事務(wù)失效。
解決方案
單數(shù)據(jù)源環(huán)境:確保配置正確的事務(wù)管理器
多數(shù)據(jù)源環(huán)境:指定使用的事務(wù)管理器
@Configuration @EnableTransactionManagement public class MultiDatabaseConfig { @Bean public DataSource primaryDataSource() { // 主數(shù)據(jù)源配置... return new HikariDataSource(); } @Bean public DataSource secondaryDataSource() { // 次數(shù)據(jù)源配置... return new HikariDataSource(); } @Bean public PlatformTransactionManager primaryTransactionManager() { return new DataSourceTransactionManager(primaryDataSource()); } @Bean public PlatformTransactionManager secondaryTransactionManager() { return new DataSourceTransactionManager(secondaryDataSource()); } } @Service public class UserService { // 指定使用的事務(wù)管理器 @Transactional(transactionManager = "primaryTransactionManager") public void createUser(User user) { // 使用主數(shù)據(jù)源的操作 } @Transactional(transactionManager = "secondaryTransactionManager") public void createUserLog(UserLog log) { // 使用次數(shù)據(jù)源的操作 } }
總結(jié)
到此這篇關(guān)于java中Spring事務(wù)失效的8個常見案例和解決方案的文章就介紹到這了,更多相關(guān)Spring事務(wù)失效的8個常見案例內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot使用SensitiveWord實現(xiàn)敏感詞過濾
這篇文章主要為大家詳細介紹了SpringBoot如何使用SensitiveWord實現(xiàn)敏感詞過濾功能,文中示例代碼講解詳細,感興趣的小伙伴可以了解一下2023-01-01Linux環(huán)境卸載Centos7自帶的OpenJDK和安裝JDK1.8圖文教程
CentOS系統(tǒng)是開發(fā)者常用的Linux操作系統(tǒng),安裝它時會默認安裝自帶的舊版本的OpenJDK,但在開發(fā)者平時開發(fā)Java項目時還是需要完整的JDK,這篇文章主要給大家介紹了關(guān)于Linux環(huán)境卸載Centos7自帶的OpenJDK和安裝JDK1.8的相關(guān)資料,需要的朋友可以參考下2024-07-07spring?mvc?AOP切面方法未執(zhí)行的一種情況的分析和處理過程
這篇文章主要介紹了spring?mvc?AOP切面方法未執(zhí)行的一種情況的分析和處理,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-05-05java實現(xiàn)哈弗曼編碼與反編碼實例分享(哈弗曼算法)
本文介紹java實現(xiàn)哈弗曼編碼與反編碼實例,大家參考使用吧2014-01-01Spring Boot整合Swagger測試api構(gòu)建全紀錄
這篇文章主要給大家介紹了關(guān)于Spring Boot整合Swagger測試api構(gòu)建的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-01-01SWT(JFace)體驗之ApplicationWindow
SWT(JFace)體驗之ApplicationWindow2009-06-06