最近在公司有一個需求:大致上是要我去做一個產品的登入的審核接口薇芝。
因為有大量的對數據庫修改、提交以及查詢的操作做盅,我使用了@Transaction 讓這個接口交給spring事務來托管轿偎。
其中出現了修改拋出異常了(已設定了,如果輸入不符合我的規(guī)范會throw new myException)罚攀,但是數據庫數據仍被修改了。
大概在網上找了好幾種原因以及解決辦法雌澄,不過首先先介紹我當時用的解決辦法斋泄。
我所使用的解決辦法
首次認為我覺得我自己配置有問題,但是又不想深究下去了镐牺,采用了很直接的方法---手動回滾
我把這些拋出的異常改為一個發(fā)送到前端的錯誤信息炫掐,通過判斷是否有誤flag的對錯來最終執(zhí)行回滾。
大概代碼:
if (flag){
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
return.........
}
這種解決辦法簡單而且無腦,不過自己深究下去之后睬涧,也明白了其中的原因募胃,下面先介紹@Transactional事務不回滾的原因
@Transactional事務不回滾的原因
- @Transactional 注解必須作用在public的權限管理上,其余的權限管理關鍵字并不會使事物生效
- 檢查數據庫是否支持事務(例如MySql4.0 支持事務畦浓,Engine:InnoDB)
- 檢查代碼塊是否拋出異常痹束,且事務的rollback的異常是拋出異常或者是拋出異常的父類(默認是RuntimeException)
引用一下第三點原因讶请,若我在@Transactional加上(rollbackFor = { myException.class })祷嘶,應該也可以解決問題,而且改動是最少的
- 檢查事務覆蓋的代碼塊中的所有Connection是否都被這個事務覆蓋(debug檢查所有connection的autoCommit屬性是不是被事務改成了false)
- @Transactional 的事務開啟 夺溢,或者是基于接口的 或者是基于類的代理被創(chuàng)建论巍。在同一個類中一個方法調用另一個方法有事務的方法,事務是不會起作用的风响。