Spring事務失效的場景
- 異常捕獲處理:自己處理了異常,沒有拋出。解決:手動拋出
- 拋出檢查異常:配置rollbackFor屬性為Excetion
- 非public方法導致事務失效,改為public
1、異常捕獲處理
示例:
張三1000元,李四1000元,張三給李四轉賬500元
@Transactionalpublic void update(){try {// 代碼實現1(張三-500元)// 出現異常int a= 1/0;// 代碼實現2(李四+500元 )}catch (Exception e){e.printStackTrace();}}
最終結果:張三500元,李四1000元
張三-500元,但是因為出現異常,李四并沒有+500元,事務失效,沒有回滾
原因:事務通知只有捕捉到目標拋出的異常,才能進行后續的回滾處理,如果目標自己處理掉了異常,事務通知無法知悉。
解決:在catch塊添加throw new RuntimeException拋出。
@Transactionalpublic void update2(){try {// 代碼實現1(張三-500元)// 出現異常int a= 1/0;// 代碼實現2(李四+500元 )}catch (Exception e){throw new RuntimeException("轉賬失敗");}}
2、拋出檢查異常
示例:
張三1000元,李四1000元,張三給李四轉賬500元
@Transactionalpublic void update() throws FileNotFoundException{// 代碼實現1(張三-500元)// 讀一個不存在的文件new FileInputStream("aaaa");// 代碼實現2(李四+500元 )}
最終結果:張三500元,李四1000元
張三-500元,但是因為出現異常,李四并沒有+500元,事務失效,沒有回滾
原因:Spring默認只會回滾非檢查異常。
解決:配置rollbackFor屬性
@Transactional(rollbackFor = Exception.class)
3、非public方法
示例:
張三1000元,李四1000元,張三給李四轉賬500元
@Transactional(rollbackFor = Exception.class)private void update() throws FileNotFoundException{// 代碼實現1(張三-500元)// 讀一個不存在的文件new FileInputStream("aaaa");// 代碼實現2(李四+500元 )}
最終結果:張三500元,李四1000元
張三-500元,但是因為出現異常,李四并沒有+500元,事務失效,沒有回滾
原因:Spring為方法創建代理、添加事務通知、前提條件都是該方法是public的
解決:改成public方法