大家好,又見面了,我是你們的朋友全棧君。
更多Spring事務問題請通路連結:Spring事務復原疑難詳解
一,為什麼架構中根本沒有對Exception的一般子類進行復原配置,異常發生時,事務都進行了復原 ,說好的隻會對RuntimeException(Unchecked 非受檢異常)復原呢?
此時,我們就有必要了解一下,RuntimeException所包含的子類具體有哪些:

這時,或許你就明白了 : 平常代碼運作階段經常遇到的那些異常,其實都是RuntimeException的子類。
受檢異常(Checked)一般在編譯期就被檢出,這就給你造成了一個Spring對于所有異常都會發生復原的誤解。
下面給出一些受檢CHECKED異常:
二,為什麼我在執行方法的時候出現了SQL執行的Exception,預設配置的情況下,事務還是發生了復原 ? 下結論之前,我們應該仔細檢視異常資訊:
[Request processing failed; nested exception is org.springframework.dao.DuplicateKeyException:
### Error updating database. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '1' for key 1
複制
下面我會給出 一個例子:類似于直播軟體中,“禮物的購買事務”,其中有三個動作:
①Mygift數量的增加 ②Customer餘額的減少 ③consumption消費明細的增加
int a=consumpDao.insert(s);//插入消費明細
int b=customerDao.insert(customer);//此處實際應該update(customer),不然會出現重複主鍵的異常
int d=0;
if(mygift==null){//判斷禮物類型是否存在,第一次插入,而後更新
m.setMySum(s.getGiftSum());
d=mygiftDao.insert(m);
}else{
mygift.setMySum(mygift.getMySum()+s.getGiftSum());
d=mygiftDao.update(mygift);
}
if(a*b*d==1){
json.put("result",0);
json.put("msg", "購買成功");
json.put("data", "");
}else{
json.put("result",-1);
json.put("msg", "購買失敗");
json.put("data", "");
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
}
複制
在程式28行,明确指出:
int a=consumpDao.insert(s);//插入消費明細
int b=customerDao.insert(customer);//此處實際應該update(customer),不然會出現重複主鍵的異常
複制
程式運作之前,Consumption消費記錄中隻有一條資料。
程式運作,出現異常,具體如下:
[Request processing failed; nested exception is org.springframework.dao.DuplicateKeyException:
### Error updating database. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '1' for key 1
複制
對應事務中的三個動作,理論發生:
①Consumption消費明細的增加 執行成功,②Customer餘額的減少SQL語句在執行的時候發生異常,③Mygift數量增加 執行成功
程式運作後,Consumption消費記錄并沒有出現第二條:
是以此時,該事務發生了復原。org.springframework.dao.DuplicateKeyException 應該是RuntimeException的子類
三,作出結論,是SQLException屬于RuntimeException的子類?還是預設配置一般異常也會復原呢?
① 檢視接口文檔java.lang.SqlException,
java.lang.Object
|____java.lang.Throwable
|____ java.lang.Exception
|____ java.lang.SQLException
可以看出: java.lang.SqlException,确實是Exception的直接子類,屬于CHECKED受檢異常,事務是不會因為它發生復原的!
② 實際上,當我們在項目開發中加入了Spring架構以後,SQL異常都被org.springframework重寫,正如上面的重複主鍵的SQL異 常。
産生原因:很顯然該異常原因屬于一般異常,而被Spring捕捉後抛出其他自定義的RuntimeException
具體可見:org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate()
Error updating database. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '1' for key 1
複制
抛出的異常:
[Request processing failed; nested exception is org.springframework.dao.DuplicateKeyException:
複制
我們知道 org.springframework.dao.DuplicateKeyException來自spring-tx-4.0.0.RELEASE.jar
反編譯可見:
java.lang.Object
|____java.lang.Throwable
|____ java.lang.Exception
|____ java.lang.RuntimeException
|____ org.springframework.core.NestedRuntimeException
|____org.springframework.dao.DataAccessException
|____ org.springframework.dao.NonTransientDataAccessException
|____org.springframework.dao.DataIntegrityViolationException
|____org.springframework.dao.DuplicateKeyException
同樣方法可以查得:org.springframework.dao中的異常都是RuntimeException的子類
得出結論:Spring架構下,所有SQL異常都被org.springframework重寫為RuntimeException,事務是以也會發生復原!
釋出者:全棧程式員棧長,轉載請注明出處:https://javaforall.cn/161473.html原文連結:https://javaforall.cn