天天看點

Spring程式設計式事務實作方式和注意點

Spring事務使用有兩種方式:聲明式事務(如通過@Transactional實作注解方式或者xml配置方式)和程式設計式事務方式,優缺點如下:

  •   聲明式事務:通過注解和xml配置使開發者隻關注業務開發,而不需要關注事務的送出和復原,但最小粒度在方法上,不能對一塊代碼增加事務,另外也要考慮事務嵌套帶來的副作用(比如長事務)。
  •  程式設計式事務:比較靈活,需要開發者在代碼中手動的管理事務的開啟、送出、復原等操作,但若對事務了解不夠深刻,容易出錯。

這裡重點講程式設計式事務方式使用的案例和注意點,使用方式如下:

private void executeTransactional(HelpParticipationContextDTO contextDTO) {
        return transactionTemplate.execute(action ->  {
            // 1.插入使用者資訊
            int row = insertStudent();
            if(row <= 0) {
               throw new RuntimeException("插入失敗");
            }
            // 2.更新統計資訊
            updateStatistics(contextDTO);
            return true;
        });
    }
           

 預設場景下若業務處理過程中出現RuntimeException或者Error異常就會復原,詳細參考org.springframework.transaction.support.TransactionTemplate-execute方法實作,還有一種實作方式如下:

private void executeTransactional(HelpParticipationContextDTO contextDTO) {
        return transactionTemplate.execute(action ->  {
          try {
            // 1.插入使用者資訊
            int row = insertStudent();
            if(row <= 0) {
               throw new RuntimeException("插入失敗");
            }
            // 2.更新統計資訊
            updateStatistics(contextDTO);
            return true;
          } catch (Exception e) {
           TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            // status.setRollbackOnly();
            return false;
          }
        });
    }
           

這種方式隻是把目前事務标記為復原,當事務進行送出時發現該事務已經設定了復原标記,則對目前事務進行復原,這裡要看送出事務的源代碼,如下:

// org.springframework.transaction.support.AbstractPlatformTransactionManager-commit
    public final void commit(TransactionStatus status) throws TransactionException {
        if (status.isCompleted()) {
            throw new IllegalTransactionStateException(
                    "Transaction is already completed - do not call commit or rollback more than once per transaction");
        }

        DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
        // 這裡就會判斷事務的復原标記
        if (defStatus.isLocalRollbackOnly()) {
            if (defStatus.isDebug()) {
                logger.debug("Transactional code has requested rollback");
            }
            processRollback(defStatus, false);
            return;
        }

        if (!shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) {
            if (defStatus.isDebug()) {
                logger.debug("Global transaction is marked as rollback-only but transactional code requested commit");
            }
            processRollback(defStatus, true);
            return;
        }

        processCommit(defStatus);
    }    
           

總結一下,當業務出現了RuntimeException或者Error異常,Spring事務進行復原,另外程式設計式事務對代碼控制比較靈活,但是建立在對Spring事務原理了解的基礎上(上面總結了程式設計式事務使用的兩種方式)。