Java異常與事物回滾探究


 

 

 

非運行時異常(checke Exception)是RuntimeException以外的異常,類型上都屬於Exception類及其子類。如IOException、SQLException等以及
用戶自定義的Exception異常。對於這種異常,JAVA編譯器強制要求我們必需對出現的這些異常進行catch並處理,否則程序就不能編譯通過。所以,
面對這種異常不管我們是否願意,只能自己去寫一大堆catch塊去處理可能的異常。
spring 事務注解

  默認遇到throw new RuntimeException("...");會回滾
  需要捕獲的throw new Exception("...");不會回滾

// 指定不回滾
@Transactional(rollbackFor=Exception.class) 
public void methodName() {
// 不會回滾
throw new Exception("...");
} 
//指定回滾
@Transactional(noRollbackFor=Exception.class)
public ItimDaoImpl getItemDaoImpl() {
// 會回滾
throw new RuntimeException("注釋");
}
我的測試

employeeEntity = employeeDao.saveOrUpdate(employeeEntityDB);
}else{
employeeEntity = employeeDao.saveOrUpdate(employeeEntity);
}
if(employeeEntity.getEmployeeName().length()>0){
throw new SQLException("sss");
}
return employeeEntity;

 

如果我主動拋出 throw new SQLException("sss");

 

結果沒有回滾,按照上面說的,SQLException不是runtimeException,所以不會回滾,實際證明也是如此

如果我主動拋出runtimeEception異常,結果證明確實回滾了

 

而對於 if(employeeEntity.getEmployeeName().length()>0){
throw new Exception("sss");
}

Exception是運行時異常和非運行時異常的父類,實際也是必須捕獲的,而測試發現,拋出此類異常不能產生事物回滾

剛剛我又在DAO部分拋出Exceotion異常,在service繼續拋出,結果仍然是沒有數據回滾,在此驗證了拋Exception異常是不回滾的!!!

轉自 http://www.linuxidc.com/Linux/2014-03/98885.htm

 

 

 

近日測試用例,發現這樣一個現象:


在業務代碼中,有如下兩種情況,比如:
throw new RuntimeException("xxxxxxxxxxxx"); 事務回滾
throw new Exception("xxxxxxxxxxxx"); 事務沒有回滾

 

自以為很了解事務,或許時間久遠的緣故,沒分析出來何故,遂查閱了下資料,寫下了如下的內容,供參考:

 

1).Spring的AOP即聲明式事務管理默認是針對unchecked exception回滾。也就是默認對RuntimeException()異常或是其子類進行事務回滾;checked異常,即Exception可try{}捕獲的不會回滾,如果使用try-catch捕獲拋出的unchecked異常后沒有在catch塊中采用頁面硬編碼的方式使用spring api對事務做顯式的回滾,則事務不會回滾, “將異常捕獲,並且在catch塊中不對事務做顯式提交=生吞掉異常” ,要想捕獲非運行時異常則需要如下配置:

解決辦法:
1.在針對事務的類中拋出RuntimeException異常,而不是拋出Exception。
2.在txAdive中增加rollback-for,里面寫自己的exception,例如自己寫的exception:

<tx:advice id="txAdvice" transaction-manager="transactionManager">
   <tx:attributes>
     <tx:method name="*" rollback-for="com.cn.untils.exception.XyzException"/>
   </tx:attributes>
 </tx:advice>
 
或者
定義不會滾的異常


<tx:advice id="txAdvice">
    <tx:attributes>
       <tx:method name="update*" no-rollback-for="IOException"/>
       <tx:method name="*"/>
    </tx:attributes>
 </tx:advice>

 
2).spring的事務邊界是在調用業務方法之前開始的,業務方法執行完畢之后來執行commit or rollback(Spring默認取決於是否拋出runtime異常).
 如果拋出runtime exception 並在你的業務方法中沒有catch到的話,事務會回滾。 
 一般不需要在業務方法中catch異常,如果非要catch,在做完你想做的工作后(比如關閉文件等)一定要拋出runtime exception,否則spring會將你的操作commit,這樣就會產生臟數據.所以你的catch代碼是畫蛇添足。
 
如:
try {  
    //bisiness logic code  
} catch(Exception e) {  
    //handle the exception  
}  

 由此可以推知,在spring中如果某個業務方法被一個 整個包裹起來,則這個業務方法也就等於脫離了spring事務的管理,因為沒有任何異常會從業務方法中拋出!全被捕獲並吞掉,導致spring異常拋出觸發事務回滾策略失效。
 不過,如果在catch代碼塊中采用頁面硬編碼的方式使用spring api對事務做顯式的回滾,這樣寫也未嘗不可。
 
 3).基於注解的事務:

 Transactional的異常控制,默認是Check Exception 不回滾,unCheck Exception回滾
 如果配置了rollbackFor 和 noRollbackFor 且兩個都是用同樣的異常,那么遇到該異常,還是回滾
 rollbackFor 和noRollbackFor 配置也許不會含蓋所有異常,對於遺漏的按照Check Exception 不回滾,unCheck Exception回滾

轉自  https://blog.csdn.net/paul342/article/details/52330609

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM