美文网首页
Spring中@Transactional注解到底做了什么(六)

Spring中@Transactional注解到底做了什么(六)

作者: 夜流星_9775 | 来源:发表于2020-04-18 16:30 被阅读0次

    回到上一章的invokeWithinTransaction方法,我们来看看事物的回滚方法completeTransactionAfterThrowing

    protected void completeTransactionAfterThrowing(@Nullable TransactionInfo txInfo, Throwable ex) {
            //当抛出异常时首先判断当前是否存在事务
            if (txInfo != null && txInfo.getTransactionStatus() != null) {
                if (logger.isTraceEnabled()) {
                    logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() +
                            "] after exception: " + ex);
                }
                //rollbackOn (ex instanceof RuntimeException || ex instanceof Error);
                //判断异常类型
                if (txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex)) {
                    try {
                        //根据 TransactionStatus 信息进行回滚处理
                        txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
                    }
                    catch (TransactionSystemException ex2) {
                        logger.error("Application exception overridden by rollback exception", ex);
                        ex2.initApplicationException(ex);
                        throw ex2;
                    }
                    catch (RuntimeException | Error ex2) {
                        logger.error("Application exception overridden by rollback exception", ex);
                        throw ex2;
                    }
                }
                else {
                    // We don't roll back on this exception.
                    // Will still roll back if TransactionStatus.isRollbackOnly() is true.
                    //如果不满足回滚条件即使抛出异常也同样会提交
                    try {
                        txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
                    }
                    catch (TransactionSystemException ex2) {
                        logger.error("Application exception overridden by commit exception", ex);
                        ex2.initApplicationException(ex);
                        throw ex2;
                    }
                    catch (RuntimeException | Error ex2) {
                        logger.error("Application exception overridden by commit exception", ex);
                        throw ex2;
                    }
                }
            }
        }
    

    这里看一个rollbackOn方法,这个方法用来判断异常类型
    默认情况下Spring中的亊务异常处理机制只对RuntimeException和Error两种情况感兴趣,我们可以利用注解方式来改变,例如:
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)

    @Override
        public boolean rollbackOn(Throwable ex) {
            return (ex instanceof RuntimeException || ex instanceof Error);
        }
    

    然后看看rollback方法

        @Override
        public final void rollback(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;
            processRollback(defStatus, false);
        }
    

    再看看processRollback方法

        private void processRollback(DefaultTransactionStatus status, boolean unexpected) {
            try {
                boolean unexpectedRollback = unexpected;
    
                try {
                    //激活
                    triggerBeforeCompletion(status);
    
                    //如果有保存点 当前事务为单独的线程则会退到保存点
                    if (status.hasSavepoint()) {
                        if (status.isDebug()) {
                            logger.debug("Rolling back transaction to savepoint");
                        }
                        status.rollbackToHeldSavepoint();
                    }
                    //如果当前事务为独立的新事务 ,则直接回退
                    else if (status.isNewTransaction()) {
                        if (status.isDebug()) {
                            logger.debug("Initiating transaction rollback");
                        }
                        doRollback(status);
                    }
                    else {
                        // Participating in larger transaction
                        //如果不是独立的事务,那么只标记状态,等到事务链执行完毕后统一回滚
                        if (status.hasTransaction()) {
                            if (status.isLocalRollbackOnly() || isGlobalRollbackOnParticipationFailure()) {
                                if (status.isDebug()) {
                                    logger.debug("Participating transaction failed - marking existing transaction as rollback-only");
                                }
                                doSetRollbackOnly(status);
                            }
                            else {
                                if (status.isDebug()) {
                                    logger.debug("Participating transaction failed - letting transaction originator decide on rollback");
                                }
                            }
                        }
                        else {
                            logger.debug("Should roll back transaction but cannot - no transaction available");
                        }
                        // Unexpected rollback only matters here if we're asked to fail early
                        if (!isFailEarlyOnGlobalRollbackOnly()) {
                            unexpectedRollback = false;
                        }
                    }
                }
                catch (RuntimeException | Error ex) {
                    triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
                    throw ex;
                }
    
                triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
    
                // Raise UnexpectedRollbackException if we had a global rollback-only marker
                if (unexpectedRollback) {
                    throw new UnexpectedRollbackException(
                            "Transaction rolled back because it has been marked as rollback-only");
                }
            }
            finally {
                //清空记录 并将挂起的资源恢复
                cleanupAfterCompletion(status);
            }
        }
    

    首先直接看下doRollback方法

        @Override
        protected void doRollback(DefaultTransactionStatus status) {
            DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
            Connection con = txObject.getConnectionHolder().getConnection();
            if (status.isDebug()) {
                logger.debug("Rolling back JDBC transaction on Connection [" + con + "]");
            }
            try {
                //数据库的回滚方法
                con.rollback();
            }
            catch (SQLException ex) {
                throw new TransactionSystemException("Could not roll back JDBC transaction", ex);
            }
        }
    

    可以看到事务的回滚,其实底层还是依靠的数据库的回滚操作

    相关文章

      网友评论

          本文标题:Spring中@Transactional注解到底做了什么(六)

          本文链接:https://www.haomeiwen.com/subject/kiobvhtx.html