springBoot service層 事務控制


springBoot使用事物比較簡單,在Application啟動類s上添加@EnableTransactionManagement注解,然后在service層的方法上添加@Transactional注解

@Transactional屬性 

屬性 類型 描述
value String 可選的限定描述符,指定使用的事務管理器
propagation enum: Propagation 可選的事務傳播行為設置
isolation enum: Isolation 可選的事務隔離級別設置
readOnly boolean 讀寫或只讀事務,默認讀寫
timeout int (in seconds granularity) 事務超時時間設置
rollbackFor Class對象數組,必須繼承自Throwable 導致事務回滾的異常類數組
rollbackForClassName 類名數組,必須繼承自Throwable 導致事務回滾的異常類名字數組
noRollbackFor Class對象數組,必須繼承自Throwable 不會導致事務回滾的異常類數組
noRollbackForClassName 類名數組,必須繼承自Throwable 不會導致事務回滾的異常類名字數組

用法:

       @Transactional 可以作用於接口、接口方法、類以及類方法上。當作用於類上時,該類的所有 public 方法將都具有該類型的事務屬性,同時,我們也可以在方法級別使用該標注來覆蓋類級別的定義。

         雖然 @Transactional 注解可以作用於接口、接口方法、類以及類方法上,但是 Spring 建議不要在接口或者接口方法上使用該注解,因為這只有在使用基於接口的代理時它才會生效。另外, @Transactional 注解應該只被應用到 public 方法上,這是由 Spring AOP 的本質決定的。如果你在 protected、private 或者默認可見性的方法上使用 @Transactional 注解,這將被忽略,也不會拋出任何異常。

        默認情況下,只有來自外部的方法調用才會被AOP代理捕獲,也就是,類內部方法調用本類內部的其他方法並不會引起事務行為,即使被調用方法使用@Transactional注解進行修飾。

  

  注解在方法上:

@Autowired private MyBatisDao dao; @Transactional @Override public void insert(Test test) { dao.insert(test); throw new RuntimeException("test");//拋出unchecked異常,觸發事物,回滾 
}  

  

    @Transactional(noRollbackFor=RuntimeException.class)  
    @Override  
    public void insert(Test test) {  
        dao.insert(test);  
        //拋出unchecked異常,觸發事物,noRollbackFor=RuntimeException.class,不回滾  
        throw new RuntimeException("test");  
    }  

  

@Transactional(propagation=Propagation.NOT_SUPPORTED)  
@Override  
public void insert(Test test) {  
    //事物傳播行為是PROPAGATION_NOT_SUPPORTED,以非事務方式運行,不會存入數據庫  
    dao.insert(test);  
}  

  注解在類上:當作用於類上時,該類的所有 public 方法將都具有該類型的事務屬性

@Transactional  
public class MyBatisServiceImpl implements MyBatisService {  
  
    @Autowired  
    private MyBatisDao dao;  
      
      
    @Override  
    public void insert(Test test) {  
        dao.insert(test);  
        //拋出unchecked異常,觸發事物,回滾  
        throw new RuntimeException("test");  
    }  

 

注意:有時候在開發時往往出現了添加注解后卻無法回滾

原因:默認spring事務只在發生未被捕獲的 RuntimeException 時才回滾。  
spring aop  異常捕獲原理:被攔截的方法需顯式拋出異常,並不能經任何處理,這樣aop代理才能捕獲到方法的異常,才能進行回滾,默認情況下aop只捕獲 RuntimeException 的異常,但可以通過配置來捕獲特定的異常並回滾  
換句話說在service的方法中不使用try catch 或者在catch中最后加上throw new runtimeexcetpion(),這樣程序異常時才能被aop捕獲進而回滾。

 

解決方案:

  1.在service層方法拋出RuntimeException異常(如在Catch中需要拋出自定義的異常則只需自定義異常繼承RuntimeException即可),並繼續捕獲和處理這個異常。

  2.在service層方法的catch語句中增加:

    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

  語句,手動回滾,這樣上層就無需去處理異常。

 


免責聲明!

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



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