乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      Spring 事務(wù)傳遞與隔離

       印度阿三17 2019-10-27

      本文討論下Spring注解@Transactional 及其隔離(isolation)和傳播(propagation)屬性的設(shè)置.

      1. @Transactional注解

      @Transactional注解可以用在數(shù)據(jù)庫事務(wù)操作的方法上。并可以設(shè)置事務(wù)的相關(guān)屬性:隔離屬性(isolation), 超時屬性(timeout), 只讀屬性(read-only)以及回滾條件,也可以指定事務(wù)管理器。

      1.1. 實現(xiàn)細節(jié)

      Spring創(chuàng)建代理或操縱類字節(jié)碼來管理事務(wù)的創(chuàng)建、提交和回滾。使用代理方式Spring會忽略內(nèi)部方法調(diào)用事務(wù),即使有@Transactional注解也會被忽略,代理需要通過其他類進行調(diào)用。
      例如,一個方法callMethod并標(biāo)記了 @Transactional注解,Spring會包裝一些事務(wù)管理代碼環(huán)繞在方法執(zhí)行過程:

      createTransactionIfNecessary();
      try {
          callMethod();
          commitTransactionAfterReturning();
      } catch (exception) {
          completeTransactionAfterThrowing();
          throw exception;
      }

      1.2. 使用@Transactional注解

      事務(wù)注解可以在接口、類或直接在方法上。實際會按照優(yōu)先級進行覆蓋,從低到高優(yōu)先級為:接口、父類、類、接口方法、父類方法、類方法。

      對于類級別注解,則Spring應(yīng)用注解設(shè)置至所有沒有標(biāo)記注解的public方法,如果在private、protecte方法上使用注解,Spring會忽略。
      下面通過示例說明:

      @Transactional
      public interface TransferService {
          void transfer(String user1, String user2, double val);
      }

      通常不建議在接口上設(shè)置事務(wù),但在Spring Data @Repository情況下是可行的。這里在類上增加注解覆蓋接口或父類的設(shè)置:

      @Service
      @Transactional
      public class TransferServiceImpl implements TransferService {
          @Override
          public void transfer(String user1, String user2, double val) {
              // ...
          }
      }

      如果在方法增加注解則覆蓋類定義:

      @Transactional
      public void transfer(String user1, String user2, double val) {
          // ...
      }

      2. 事務(wù)傳播

      傳播性定義業(yè)務(wù)邏輯的事務(wù)邊界。Spring根據(jù)傳播性設(shè)置負責(zé)啟動或暫停事務(wù)。

      Spring根據(jù)傳播屬性調(diào)用TransactionManager::getTransaction 方法獲取或創(chuàng)建事務(wù)。它支持所有類型的TransactionManager的部分傳播屬性,一些傳播屬性僅被TransactionManager特定實現(xiàn)支持。下面詳細描述不同傳播屬性。

      2.1. REQUIRED

      REQUIRED是缺省屬性。Spring檢查是否有活動事務(wù),如果沒有則創(chuàng)建新的事務(wù),否則業(yè)務(wù)邏輯追加至當(dāng)前活動事務(wù)中:

      @Transactional(propagation = Propagation.REQUIRED)
      public void requiredExample(String user) { 
          // ... 
      }

      缺省屬性也可以不指定:

      @Transactional
      public void requiredExample(String user) { 
          // ... 
      }

      對應(yīng)偽代碼如下:

      if (isExistingTransaction()) {
          if (isValidateExistingTransaction()) {
              validateExisitingAndThrowExceptionIfNotValid();
          }
          return existing;
      }
      return createNewTransaction();

      2.2. SUPPORTS

      SUPPORTS屬性,Spring首先檢查是否有活動事務(wù)存在,存在則使用,反之,則無事務(wù)進行執(zhí)行。

      @Transactional(propagation = Propagation.SUPPORTS)
      public void supportsExample(String user) { 
          // ... 
      }

      對應(yīng)偽代碼:

      if (isExistingTransaction()) {
          if (isValidateExistingTransaction()) {
              validateExisitingAndThrowExceptionIfNotValid();
          }
          return existing;
      }
      return emptyTransaction;

      2.3. MANDATORY

      當(dāng)屬性設(shè)置為MANDATORY屬性時,如果存在活動事務(wù),則使用之。反之拋異常,即強制使用事務(wù)。

      @Transactional(propagation = Propagation.MANDATORY)
      public void mandatoryExample(String user) { 
          // ... 
      }

      對應(yīng)偽代碼:

      if (isExistingTransaction()) {
          if (isValidateExistingTransaction()) {
              validateExisitingAndThrowExceptionIfNotValid();
          }
          return existing;
      }
      throw IllegalTransactionStateException;

      2.4. NEVER

      NEVER屬性的邏輯:如果存在活動事務(wù)則拋異常。

      @Transactional(propagation = Propagation.NEVER)
      public void neverExample(String user) { 
          // ... 
      }

      對應(yīng)偽代碼:

      if (isExistingTransaction()) {
          throw IllegalTransactionStateException;
      }
      return emptyTransaction;

      2.5. NOT_SUPPORTED

      如果存在活動事務(wù)則Spring首先掛起當(dāng)前事務(wù),然后業(yè)務(wù)邏輯在無事務(wù)下執(zhí)行。

      @Transactional(propagation = Propagation.NOT_SUPPORTED)
      public void notSupportedExample(String user) { 
          // ... 
      }

      JTATransactionManager支持開箱即用的事務(wù)掛起。其他方法通過持有對事務(wù)引用,然后從線程上下文中清除它來模擬掛起。

      2.6. REQUIRES_NEW

      REQUIRES_NEW屬性,如果存在活動事務(wù)則Spring掛起當(dāng)前事務(wù),然后創(chuàng)建新的事務(wù)。

      @Transactional(propagation = Propagation.REQUIRES_NEW)
      public void requiresNewExample(String user) { 
          // ... 
      }

      與NOT_SUPPORTED類似,我們需要JTATransactionManager來執(zhí)行實際的事務(wù)掛起。
      偽代碼如下:

      if (isExistingTransaction()) {
          suspend(existing);
          try {
              return createNewTransaction();
          } catch (exception) {
              resumeAfterBeginException();
              throw exception;
          }
      }
      return createNewTransaction();

      2.7. NESTED

      對于NESTED屬性,Spring檢查是否存在事務(wù),如果存在則標(biāo)記保存點。意味著如果后續(xù)業(yè)務(wù)執(zhí)行遇到異常,那么回滾至保存點。如果沒有活動事務(wù)時與REQUIRED屬性一樣。

      DataSourceTransactionManager 支持該屬性,一些JTATransactionManager的實現(xiàn)可能也支持。JpaTransactionManager僅對JDBC連接支持NESTED屬性,如果設(shè)置nestedTransactionAllowed 屬性為true且JDBC驅(qū)動支持保存點,那么JPA事務(wù)中的JDBC代碼也工作。屬性設(shè)置如下:

      @Transactional(propagation = Propagation.NESTED)
      public void nestedExample(String user) { 
          // ... 
      }

      3. 事務(wù)隔離

      隔離屬性是ACID ( Atomicity, Consistency, Isolation及 Durability)其中之一,隔離描述并發(fā)事務(wù)應(yīng)用的更改如何對彼此可見。每種隔離級別防止事務(wù)中零個或多個并發(fā)副作用:

      • 臟讀(Dirty read): 讀取并發(fā)事務(wù)中未提交的信息

      • 不可重復(fù)讀(Nonrepeatable read): 如果并發(fā)事務(wù)更新相同行并提交,重復(fù)讀一行獲得不同值

      • 幻讀(Phantom read): 如果其他事務(wù)增加或刪除查詢行并提交,則重復(fù)查詢一定范圍記錄返回值不同

      我們可以通過@Transactional::isolation設(shè)置事務(wù)的隔離級別。Spring提供了5個枚舉值:DEFAULT, READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE。

      3.1. 缺省隔離屬性

      當(dāng)Spring創(chuàng)建新事務(wù)時,缺省隔離級別使用RDBMS,因此改變數(shù)據(jù)庫時應(yīng)該注意。
      我們也應(yīng)該考慮使用不同隔離屬性調(diào)用一組方法的場景,正常流程隔離僅應(yīng)用于新事務(wù)創(chuàng)建時。因此出于某種原因,不想讓一個方法在不同的隔離狀態(tài)下執(zhí)行,我們必須將TransactionManager::setValidateExistingTransaction設(shè)置為true。偽代碼如下:

      if (isolationLevel != ISOLATION_DEFAULT) {
          if (currentTransactionIsolationLevel() != isolationLevel) {
              throw IllegalTransactionStateException
          }
      }

      下面看看其他隔離級別。

      3.2. READ_UNCOMMITTED

      READ_UNCOMMITTED是最低的隔離級別,最大化允許并發(fā)訪問。
      它受到上述三種并發(fā)性副作用的影響。具有此隔離的事務(wù)將讀取其他并發(fā)事務(wù)未提交數(shù)據(jù),此外不可重復(fù)讀取和幻讀都可能發(fā)生。因此我們可以在重新讀取行或重新執(zhí)行范圍查詢時獲得不同的結(jié)果??梢栽诜椒ɑ蝾惿显O(shè)置隔離級別:

      @Transactional(isolation = Isolation.READ_UNCOMMITTED)
      public void log(String message) {
          // ...
      }

      Postgres 不支持 READ_UNCOMMITTED 隔離屬性,會用 READ_COMMITED 代替。Oracle 也不支持 READ_UNCOMMITTED。

      3.3. READ_COMMITTED

      第二級隔離READ_COMMITTED可以防止臟讀,其他并發(fā)副作用仍可能發(fā)生。并發(fā)事務(wù)的未提交改變沒有影響,但已提交的改變再次查詢也會改變。
      設(shè)置隔離代碼:

      @Transactional(isolation = Isolation.READ_COMMITTED)
      public void log(String message){
          // ...
      }

      READ_COMMITTED Postgres, SQL Server及Oracle的缺省級別。

      3.4. REPEATABLE_READ

      第三個隔離級別是REPEATABLE_READ,防止臟讀和不可重復(fù)讀,因此不會受并發(fā)事務(wù)未提交改變影響。當(dāng)重復(fù)查詢行不會得到不同結(jié)果,但可能獲得新增記錄或刪除部分行。

      該級別可以防止丟失更新,當(dāng)兩個或多個并發(fā)事務(wù)讀并更新相同行會發(fā)生丟失更新。REPEATABLE_READ根本不允許同時訪問行,因此丟失更新不會發(fā)生。

      設(shè)置代碼:

      @Transactional(isolation = Isolation.REPEATABLE_READ) 
      public void log(String message){
          // ...
      }

      REPEATABLE_READ Mysql的缺省級別,Oracle 不支持 REPEATABLE_READ。

      3.5. SERIALIZABLE

      SERIALIZABLE 是最高隔離級別。可以防止上述所有的問題,但也導(dǎo)致最低并發(fā)訪問效率,因為并發(fā)事務(wù)按照順序執(zhí)行。也就是并發(fā)執(zhí)行一組SERIALIZABLE級別事務(wù)與順序執(zhí)行結(jié)果一樣。設(shè)置代碼:

      @Transactional(isolation = Isolation.SERIALIZABLE)
      public void log(String message){
          // ...
      }

      4. 總結(jié)

      本文我們探討了事務(wù)的傳遞與隔離屬性,并詳細解釋了不同屬性的含義及對并發(fā)事務(wù)的影響。

        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多