使用spring不免要用到spring的事務管理,要用事務管理又會很天然的選擇聲明式的事務管理,在spring的文檔中說道,spring聲明式事務管理默認對非檢查型異常和運行時異常進行事務回滾,而對檢查型異常則不進行回滾操做。
那麼什麼是檢查型異常什麼又是非檢查型異常呢?
最簡單的判斷點有兩個:
1.繼承自runtimeexception或error的是非檢查型異常,而繼承自exception的則是檢查型異常(固然,runtimeexception自己也是exception的子類)。java
2.對非檢查型類異常能夠不用捕獲,而檢查型異常則必須用try語句塊進行處理或者把異常交給上級方法處理總之就是必須寫代碼處理它。因此必須在service捕獲異常,而後再次拋出,這樣事務方纔起效。spring
在service類前加上@Transactional,聲明這個service全部方法須要事務管理。每個業務方法開始時都會打開一個事務。Spring默認狀況下會對運行期例外(RunTimeException)進行事務回滾。這個例外是unchecked若是遇到checked意外就不回滾。spa
若是在程序須要捕獲異常 ,則可:代理
try { doDb1(); doDb2(); } catch (Exception e) { e.printStackTrace(); TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); //若是doDb2()拋了異常,doDb1()是會回滾的 }
在catch塊中添加TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();或者再往外拋try{}catch{throw Exception}。code
在須要事務管理的地方加@Transactional 註解。@Transactional 註解能夠被應用於接口定義和接口方法、類定義和類的 public 方法上。對象
@Transactional 註解只能應用到 public 可見度的方法上。 若是你在 protected、private 或者 package-visible 的方法上使用 @Transactional 註解,它也不會報錯, 可是這個被註解的方法將不會展現已配置的事務設置。繼承
注意僅僅 @Transactional 註解的出現不足於開啓事務行爲,它僅僅 是一種元數據。必須在配置文件中使用配置元素,才真正開啓了事務行爲。接口
經過 元素的 「proxy-target-class」 屬性值來控制是基於接口的仍是基於類的代理被建立。若是 「proxy-target-class」 屬值被設置爲 「true」,那麼基於類的代理將起做用(這時須要CGLIB庫cglib.jar在CLASSPATH中)。若是 「proxy-target-class」 屬值被設置爲 「false」 或者這個屬性被省略,那麼標準的JDK基於接口的代理將起做用。事務
Spring團隊建議在具體的類(或類的方法)上使用 @Transactional 註解,而不要使用在類所要實現的任何接口上。在接口上使用 @Transactional 註解,只能當你設置了基於接口的代理時它才生效。由於註解是 不能繼承 的,這就意味着若是正在使用基於類的代理時,那麼事務的設置將不能被基於類的代理所識別,並且對象也將不會被事務代理所包裝。文檔
@Transactional 的事務開啓 ,或者是基於接口的 或者是基於類的代理被建立。因此在同一個類中一個方法調用另外一個方法有事務的方法,事務是不會起做用的。