失效場(chǎng)景匯總

使用@Transactional要注意以下幾個(gè)問題:數(shù)據(jù)庫(kù)引擎是否支持事務(wù)、Spring中是否配置開啟@Transactional事務(wù)、propgation設(shè)置錯(cuò)誤、rollbackFor設(shè)置錯(cuò)誤、catch的時(shí)候吞了異常、在同類中的普通方法調(diào)用事務(wù)方法、事務(wù)方法不是public的。
失效場(chǎng)景詳述
底層是否支持
數(shù)據(jù)庫(kù)引擎是否支持事務(wù)
使用事務(wù)首先要確認(rèn)自己選擇的數(shù)據(jù)庫(kù)引擎是否支持事務(wù),如現(xiàn)在大部分公司選擇的MySQL的innodb引擎是支持事務(wù)的
配置是否正確
Spring中是否配置開啟@Transactional事務(wù)
@EnableTransactionManagement開啟注解版本事務(wù)功能
propgation設(shè)置錯(cuò)誤
propgation定義了@Transactional的邊界:是否使用事務(wù)、在存在事務(wù)時(shí)如何表現(xiàn)
事務(wù)的傳播機(jī)制如下所示:
Propagation.REQUIRED:如果當(dāng)前存在事務(wù),則使用該事務(wù)。 如果當(dāng)前沒有事務(wù),則創(chuàng)建一個(gè)新的事務(wù)。
Propagation.REQUIRES_NEW:創(chuàng)建一個(gè)新的事務(wù),如果當(dāng)前有事務(wù),暫停當(dāng)前的事務(wù)。
Propagation.SUPPORTS:如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前不存在事務(wù),則以非事務(wù)的方式繼續(xù)運(yùn)行。
Propagation.MANDATORY:如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前不存在事務(wù),則拋出異常。
Propagation.NOT_SUPPORTED:以非事務(wù)的方式運(yùn)行,如果當(dāng)前存在事務(wù),暫停當(dāng)前的事務(wù)。
Propagation.NEVER:以非事務(wù)的方式運(yùn)行,如果當(dāng)前存在事務(wù),則拋出異常。
Propagation.NESTED:如果當(dāng)前存在事務(wù),則創(chuàng)建一個(gè)嵌套事務(wù)來運(yùn)行,如果當(dāng)前沒有事務(wù),行為等同于PROPAGATION_REQUIRED
rollbackFor設(shè)置錯(cuò)誤
定義了在拋出什么樣的異常時(shí)事務(wù)會(huì)進(jìn)行回滾。Spring默認(rèn)拋出了未檢查unchecked異常(繼承自 RuntimeException 的異常)或者 Error才回滾事務(wù)。
代碼是不是合理
catch的時(shí)候吞了異常
如果想要spring事務(wù)能夠正?;貪L,必須拋出它能夠處理的異常。如果沒有拋異常,則spring認(rèn)為程序是正常的
在同類中的普通方法調(diào)用事務(wù)方法
@Transactional事務(wù)主要是利用springAOP生產(chǎn)代理對(duì)象,然后用代理對(duì)象來進(jìn)行事務(wù)的提交,在使用JDK的動(dòng)態(tài)代理時(shí),代理類在處理完增強(qiáng)邏輯后通過反射調(diào)用了目標(biāo)類的原始方法,之后便是直接在該原始方法里面執(zhí)行邏輯,如果代理類最初調(diào)用的是一個(gè)普通的方法,那么調(diào)用該方法之前并沒有進(jìn)行增強(qiáng),而后所有的邏輯都在目標(biāo)類中執(zhí)行,因此即使此時(shí)在目標(biāo)類中調(diào)用了事務(wù)方法其實(shí)也并沒有進(jìn)行代理。因此事務(wù)會(huì)失效。
事務(wù)方法不是public的
在生成代理類時(shí),如果注解的方法不是public的話,會(huì)導(dǎo)致事務(wù)失效,原因是在AbstractFallbackTransactionAttributeSource類的computeTransactionAttribute方法中有個(gè)判斷,如果目標(biāo)方法不是public,則TransactionAttribute返回null,即不支持事務(wù)