Spring事務簡單小結

Spring 爲事務管理提供了豐富的功能支持。Spring 事務管理分爲編程式和聲明式的兩種方式。編程式事務指的是經過編碼方式實現事務;聲明式事務基於 AOP,將具體業務邏輯與事務處理解耦。聲明式事務管理使業務代碼邏輯不受污染, 所以在實際使用中聲明式事務用的比較多。聲明式事務有兩種方式,一種是在配置文件(xml)中作相關的事務規則聲明,另外一種是基於 @Transactional 註解的方式。html

須要明確聲明式事物的前提:java

異常複習:spring

若是不對運行時異常進行捕獲,那麼出現運行時異常後將會終止線程或主程序,此時事物會發生回滾,若是不想終止,可使用catch進行異常捕獲;捕獲後,接下來的代碼將繼續正常執行,事務不發生回滾;

非運行時異常(除RuntimeException之外),如IOException,SQLException等等,必須使用catch進行捕獲,不然程序就沒法經過;由於異常被捕獲,因此沒法發生回滾;sql

事務的傳播級別

經過配置propagation 屬性,能夠選擇事務的傳播行爲數據庫

可選的值有:編程

  • Propagation.REQUIRED(默認)app

    若是當前存在事務,則加入該事務,若是當前不存在事務,則建立一個新的事務。ide

    使用示例:spring-boot

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public int insertExample(AccompanyRecord accompanyRecord) {
        Student student = new Student();
      
        // myabtis接口
        studentMapper.updateAttention(student);
        accompanyRecordMapper.insertAccompanyRecord(accompanyRecord);
      
        if (true) {
          // 拋異常 回滾
          throw new RuntimeException();
        }
    }
    複製代碼

    以上兩條sql執行完後,又拋出了運行時異常,因此上面兩條sql都會進行回滾;編碼

  • Propagation.SUPPORTS

    若是當前存在事務,則加入該事務;若是當前不存在事務,則以非事務的方式繼續運行。

  • Propagation.MANDATORY

    若是當前存在事務,則加入該事務;若是當前不存在事務,則拋出異常。

  • Propagation.REQUIRES_NEW

    從新建立一個新的事務,若是當前存在事務,暫停當前的事務。

  • Propagation.NOT_SUPPORTED

    以非事務的方式運行,若是當前存在事務,暫停當前的事務。

  • Propagation.NEVER

    以非事務的方式運行,若是當前存在事務,則拋出異常。

  • Propagation.NESTED

    和 Propagation.REQUIRED 效果同樣。

事務使用的注意事項:

在默認的代理模式下,只有目標方法由外部調用,才能被 Spring 的事務攔截器攔截。在同一個類中的兩個方法直接調用,是不會被 Spring 的事務攔截器攔截;【參照Spring官方文檔】

示例:

在有需求以下,就算 save 方法的後面拋異常了,也不能影響 method1 方法的數據插入。直接給 method1 頁加入一個新的事務,這樣 method1 就會在這個新的事務中執行,原來的事務不會影響到新的事務。好比 method1 方法上面再加入註解 @Transactional,設置 propagation 屬性爲 Propagation.REQUIRES_NEW,代碼以下。

@Transactional(propagation = Propagation.REQUIRED)
@Override
public void save() {

    method1();

    User user = new User("服部半藏");
    userMapper.insertSelective(user);

    if (true) {
        throw new RuntimeException("save 拋異常了");
    }
}

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void method1() {
    User user = new User("宮本武藏");
    userMapper.insertSelective(user);
}
複製代碼

此時會發現,即便拋出異常了,仍然發生回滾;經過日誌能夠發現,從頭至尾都只有一個事物,並無建立新事物;因此咱們要想建立新事物,必須新建一個類,將該方法由外部調用,也就是新建一個類用於存放method1便可;此時會發現能夠按照需求執行;

流程:@Transactional 的 propagation 屬性爲 Propagation.REQUIRES_NEW ,因此接着暫停了 save 方法的事務,從新建立了xxx.method1 方法的事務,接着 xxx.method1 方法的事務提交,接着 save 方法的事務回滾。

事務的隔離級別

經過配置isolation 屬性,能夠選擇事務的隔離級別

可選的值有:

  • Isolation.DEFAULT(默認)

    使用底層數據庫默認的隔離級別。

  • Isolation.READ_UNCOMMITTED

  • Isolation.READ_COMMITTED

  • Isolation.REPEATABLE_READ

  • Isolation.SERIALIZABLE

@tansactional註解屬性

  • timeout 屬性 事務的超時時間,默認值爲-1。若是超過該時間限制但事務尚未完成,則自動回滾事務。

  • readOnly 屬性 指定事務是否爲只讀事務,默認值爲 false;爲了忽略那些不須要事務的方法,好比讀取數據,能夠設置 read-only 爲 true。

  • rollbackFor 屬性 用於指定可以觸發事務回滾的異常類型,能夠指定多個異常類型。

  • noRollbackFor 屬性 拋出指定的異常類型,不回滾事務,也能夠指定多個異常類型。

注:alibaba規範必須顯示聲明RollBackFor:

  1. 讓checked例外也回滾:在整個方法前加上 @Transactional(rollbackFor=Exception.class)

  2. 讓unchecked例外不回滾: @Transactional(notRollbackFor=RunTimeException.class)

  3. 不須要事務管理的(只查詢的)方法:@Transactional(propagation=Propagation.NOT_SUPPORTED)

注意: 若是異常被try{}catch{}了,事務就不回滾了,若是想讓事務回滾必須再往外拋try{}catch{throw Exception}。

事務實現機制

基於AOP,暫略

參考:
blog.csdn.net/nextyu/arti…

www.cnblogs.com/clwydjgs/p/…

www.cnblogs.com/xiaohan666/…

相關文章
相關標籤/搜索