天天看點

哪些異常是RuntimeException?Sql異常屬于RuntimeException嗎?Spring下SQL異常事務復原

大家好,又見面了,我是你們的朋友全棧君。

更多Spring事務問題請通路連結:Spring事務復原疑難詳解

一,為什麼架構中根本沒有對Exception的一般子類進行復原配置,異常發生時,事務都進行了復原 ,說好的隻會對RuntimeException(Unchecked 非受檢異常)復原呢?

此時,我們就有必要了解一下,RuntimeException所包含的子類具體有哪些:

哪些異常是RuntimeException?Sql異常屬于RuntimeException嗎?Spring下SQL異常事務復原

這時,或許你就明白了 : 平常代碼運作階段經常遇到的那些異常,其實都是RuntimeException的子類。

受檢異常(Checked)一般在編譯期就被檢出,這就給你造成了一個Spring對于所有異常都會發生復原的誤解。

下面給出一些受檢CHECKED異常:

哪些異常是RuntimeException?Sql異常屬于RuntimeException嗎?Spring下SQL異常事務復原
哪些異常是RuntimeException?Sql異常屬于RuntimeException嗎?Spring下SQL異常事務復原

二,為什麼我在執行方法的時候出現了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