返回介绍

10.3.3 事务提交

发布于 2025-04-22 22:09:16 字数 5762 浏览 0 评论 0 收藏

之前我们分析了 Spring 的事务异常处理机制,那么事务的执行并没有出现任何的异常,也就意味着事务可以走正常事务提交的流程了。

protected void commitTransactionAfterReturning(TransactionInfo txInfo) {

  if (txInfo != null && txInfo.hasTransaction()) {

   if (logger.isTraceEnabled()) {

    logger.trace("Completing transaction for [" + txInfo.getJoinpoint

    Identification() + "]");

  }

  txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());

 }

}

在真正的数据提交之前,还需要做个判断。不知道大家还有没有印象,在我们分析事务异常处理规则的时候,当某个事务既没有保存点又不是新事物,Spring 对它的处理方式只是设置一个回滚标识。这个回滚标识在这里就会派上用场了,主要的应用场景如下。

某个事务是另一个事务的嵌入事务,但是,这些事务又不在 Spring 的管理范围内,或者无法设置保存点,那么 Spring 会通过设置回滚标识的方式来禁止提交。首先当某个嵌入事务发生回滚的时候会设置回滚标识,而等到外部事务提交时,一旦判断出当前事务流被设置了回滚标识,则由外部事务来统一进行整体事务的回滚。

所以,当事务没有被异常捕获的时候也并不意味着一定会执行提交的过程。

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);

  return;

 }

  if (!shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) {

   if (defStatus.isDebug()) {

    logger.debug("Global transaction is marked as rollback-only but

    transactional code requested commit");

  }

  processRollback(defStatus);

   if (status.isNewTransaction() || isFailEarlyOnGlobalRollbackOnly()) {

    throw new UnexpectedRollbackException(

    "Transaction rolled back because it has been marked as

   rollback-only");

  }

  return;

 }

 //处理事务提交

 processCommit(defStatus);

}

而当事务执行一切都正常的时候,便可以真正地进入提交流程了。

private void processCommit(DefaultTransactionStatus status) throws TransactionException {

  try {

   boolean beforeCompletionInvoked = false;

   try {

   //预留

   prepareForCommit(status);

   //添加的 TransactionSynchronization 中的对应方法的调用

   triggerBeforeCommit(status);

   //添加的 TransactionSynchronization 中的对应方法的调用

   triggerBeforeCompletion(status);

    beforeCompletionInvoked = true;

    boolean globalRollbackOnly = false;

    if (status.isNewTransaction() || isFailEarlyOnGlobalRollbackOnly()) {

     globalRollbackOnly = status.isGlobalRollbackOnly();

   }

    if (status.hasSavepoint()) {

     if (status.isDebug()) {

      logger.debug("Releasing transaction savepoint");

    }

    //如果存在保存点则清除保存点信息

    status.releaseHeldSavepoint();

   }

    else if (status.isNewTransaction()) {

     if (status.isDebug()) {

      logger.debug("Initiating transaction commit");

    }

    //如果是独立的事务则直接提交

    doCommit(status);

   }

    if (globalRollbackOnly) {

     throw new UnexpectedRollbackException(

     "Transaction silently rolled back because it has been

     marked as rollback-only");

   }

  }

   catch (UnexpectedRollbackException ex) {

    triggerAfterCompletion(status, TransactionSynchronization.STATUS_

   ROLLED_BACK);

    throw ex;

  }

   catch (TransactionException ex) {

    if (isRollbackOnCommitFailure()) {

     doRollbackOnCommitException(status, ex);

   }

    else {

     triggerAfterCompletion(status, TransactionSynchronization.STATUS_

    UNKNOWN);

   }

    throw ex;

  }

   catch (RuntimeException ex) {

    if (!beforeCompletionInvoked) {

    triggerBeforeCompletion(status);

   }

    doRollbackOnCommitException(status, ex);

    throw ex;

  }

   catch (Error err) {

    if (!beforeCompletionInvoked) {

    //添加的 TransactionSynchronization 中的对应方法的调用

    triggerBeforeCompletion(status);

   }

   //提交过程中出现异常则回滚

    doRollbackOnCommitException(status, err);

    throw err;

  }

   try {

   //添加的 TransactionSynchronization 中的对应方法的调用

   triggerAfterCommit(status);

  }

   finally {

    triggerAfterCompletion(status, TransactionSynchronization.STATUS_

   COMMITTED);

  }

 }

  finally {

  cleanupAfterCompletion(status);

 }

}

在提交过程中也并不是直接提交的,而是考虑了诸多的方面,符合提交的条件如下。

当事务状态中有保存点信息的话便不会去提交事务。

当事务非新事务的时候也不会去执行提交事务操作。

此条件主要考虑内嵌事务的情况,对于内嵌事务,在 Spring 中正常的处理方式是将内嵌事务开始之前设置保存点,一旦内嵌事务出现异常便根据保存点信息进行回滚,但是如果没有出现异常,内嵌事务并不会单独提交,而是根据事务流由最外层事务负责提交,所以如果当前存在保存点信息便不是最外层事务,不做保存操作,对于是否是新事务的判断也是基于此考虑。

如果程序流通过了事务的层层把关,最后顺利地进入了提交流程,那么同样,Spring 会将事务提交的操作引导至底层数据库连接的 API,进行事务提交。

protected void doCommit(DefaultTransactionStatus status) {

  DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.

 getTransaction();

  Connection con = txObject.getConnectionHolder().getConnection();

  if (status.isDebug()) {

   logger.debug("Committing JDBC transaction on Connection [" + con + "]");

 }

  try {

  con.commit();

 }

  catch (SQLException ex) {

   throw new TransactionSystemException("Could not commit JDBC transaction", ex);

 }

}

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。