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

Spring AOP的代理機(jī)制默認(rèn)只攔截public方法。
這是因?yàn)槭聞?wù)通知是基于Spring AOP實(shí)現(xiàn)的,而Spring AOP默認(rèn)只攔截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注解會(huì)被直接忽略,返回null,導(dǎo)致事務(wù)不生效。
解決方案
確保標(biāo)注@Transactional的方法為public:

二、同一個(gè)類中方法調(diào)用
問(wèn)題現(xiàn)象
在同一個(gè)類中,非事務(wù)方法調(diào)用事務(wù)方法,或者事務(wù)方法調(diào)用另一個(gè)具有不同事務(wù)屬性的方法,事務(wù)會(huì)失效。

原理分析

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

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

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

三、異常被吞沒(méi)
問(wèn)題現(xiàn)象
開(kāi)發(fā)者在事務(wù)方法中捕獲了異常但沒(méi)有重新拋出,導(dǎo)致事務(wù)無(wú)法回滾。

原理分析

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

方法2:使用TransactionAspectSupport手動(dòng)回滾

四、異常類型不匹配回滾規(guī)則
問(wèn)題現(xiàn)象
開(kāi)發(fā)者拋出了異常,但事務(wù)沒(méi)有回滾。
這通常是因?yàn)閽伋龅漠惓n愋筒粷M足默認(rèn)的回滾規(guī)則。

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

方法2:將受檢異常轉(zhuǎn)換為非受檢異常

五、數(shù)據(jù)庫(kù)不支持事務(wù)
問(wèn)題現(xiàn)象
所有事務(wù)配置看起來(lái)都正確,但事務(wù)仍然不生效。
原理分析

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

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

使用不當(dāng)?shù)膫鞑バ袨闀?huì)導(dǎo)致事務(wù)范圍不符合預(yù)期,特別是在異常處理場(chǎng)景中。
解決方案
根據(jù)業(yè)務(wù)需求選擇正確的傳播行為:

傳播行為選擇指南:

七、未被Spring管理的類
問(wèn)題現(xiàn)象
在類上添加了@Transactional注解,但事務(wù)沒(méi)有生效。

原理分析

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

如果配置了錯(cuò)誤的事務(wù)管理器,或者在多數(shù)據(jù)源環(huán)境中未指定正確的事務(wù)管理器,會(huì)導(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個(gè)常見(jiàn)案例和解決方案的文章就介紹到這了,更多相關(guān)Spring事務(wù)失效的8個(gè)常見(jiàn)案例內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用Swagger時(shí)Controller中api接口顯示不全的問(wèn)題分析及解決
swagger是一個(gè)十分好用的api接口管理、測(cè)試框架,現(xiàn)在越來(lái)越多的人使用這個(gè)做接口的測(cè)試和管理,但經(jīng)常遇到Controller中的api接口顯示不全的問(wèn)題,所以本文給大家詳細(xì)分析了問(wèn)題以及解決方法,需要的朋友可以參考下2024-02-02
springsecurity實(shí)現(xiàn)用戶登錄認(rèn)證快速使用示例代碼(前后端分離項(xiàng)目)
這篇文章主要介紹了springsecurity實(shí)現(xiàn)用戶登錄認(rèn)證快速使用示例代碼(前后端分離項(xiàng)目),本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2024-03-03
apollo與springboot集成實(shí)現(xiàn)動(dòng)態(tài)刷新配置的教程詳解
這篇文章主要介紹了apollo與springboot集成實(shí)現(xiàn)動(dòng)態(tài)刷新配置,本文分步驟給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-06-06
mybatis?plus實(shí)現(xiàn)分頁(yè)邏輯刪除
這篇文章主要為大家介紹了mybatis?plus實(shí)現(xiàn)分頁(yè)邏輯刪除的方式詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05
基于HttpClient在HTTP協(xié)議接口測(cè)試中的使用(詳解)
下面小編就為大家?guī)?lái)一篇基于HttpClient在HTTP協(xié)議接口測(cè)試中的使用(詳解)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-10-10
JAVA使用ElasticSearch查詢in和not in的實(shí)現(xiàn)方式
今天小編就為大家分享一篇關(guān)于JAVA使用Elasticsearch查詢in和not in的實(shí)現(xiàn)方式,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2018-12-12
java讀寫(xiě)excel文件實(shí)現(xiàn)POI解析Excel的方法
在日常工作中,我們常常會(huì)進(jìn)行Excel文件讀寫(xiě)操作,這篇文章主要介紹了java讀寫(xiě)excel文件實(shí)現(xiàn)POI解析Excel的方法,實(shí)例分析了java讀寫(xiě)excel的技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2018-10-10

