異常捕獲和丟擲你理解的到位嗎,是否你也存在這樣的錯誤?
阿新 • • 發佈:2019-01-11
今天在公司運維人員反饋出現了很多資料丟失的問題.
我組織開發人員進行了重現,重現之後開發人員進行修復.他們的修復方式是try catch 一下,然後在丟擲異常的地方回滾,以為修復好了就提交程式碼下班了.
我做程式碼走查時發現了問題, 這也是很多不注意細節的程式設計師或剛工作不久的程式設計師常犯的錯誤:
在dao層的所有方法都用了try catch 攔截,在servic層又進行了try catch 攔截,spring配置在service層控制事務.
用以下程式碼還原場景:
這樣的程式碼,如果在執行userDao.updateUser(user) 報錯時,userDao.addUser(user)依然執行成功入庫了.為什麼呢? 答案是spring的事務配置在了UserService類的updateUser方法上,只有這個方法執行時丟擲異常了才回滾事務,現在的程式碼" 永遠"都不可能把錯誤 SQLException 丟擲給spring捕獲,spring沒有捕獲到異常就會提交事務.
簡單的用虛擬碼說明一下spring的事務處理吧: aop spring 開啟事務 try {
執行實際方法(如上例中的updateService) spring 提交事務 }catch(Exception e){ spring 回滾事務
}finally{
public class UserDao { public voidaddUser(User user) throws SQLException{ try { sqlMap.add("addUser",user); }catch (SQLException e){ e.printStackTrace(); } } public void updateUser(User user) throws SQLException{ try { sqlMap.add("updateUser",user); }catch(SQLException e){ e.printStackTrace(); } }
}
public class UserService { UserDao userDao = new UserDao(); public void updateUser(User user) throws SQLException { try { //...... userDao.addUser(user); //...... userDao.updateUser(user); //..... }catch (SQLException e){ e.printStackTrace(); } } }
spring 開啟事務在service層,配置程式碼略.
這樣的程式碼,如果在執行userDao.updateUser(user) 報錯時,userDao.addUser(user)依然執行成功入庫了.為什麼呢? 答案是spring的事務配置在了UserService類的updateUser方法上,只有這個方法執行時丟擲異常了才回滾事務,現在的程式碼" 永遠"都不可能把錯誤 SQLException 丟擲給spring捕獲,spring沒有捕獲到異常就會提交事務.
簡單的用虛擬碼說明一下spring的事務處理吧: aop spring 開啟事務 try {
執行實際方法(如上例中的updateService) spring 提交事務 }catch(Exception e){ spring 回滾事務
}finally{
xxxx}