Spring事务-3

待整理

AbstractPlatformTransactionManager

   public final TransactionStatus getTransaction(TransactionDefinition definition)
        throws TransactionException
    {
        Object transaction = doGetTransaction();
        boolean debugEnabled = logger.isDebugEnabled();
        if(definition == null)
            definition = new DefaultTransactionDefinition();
        if(isExistingTransaction(transaction))
            return handleExistingTransaction(definition, transaction, debugEnabled);
        if(definition.getTimeout() < -1)
            throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout());
        if(definition.getPropagationBehavior() == 2)
            throw new IllegalTransactionStateException("No existing transaction found for transaction marked with propagation 'mandatory'");
        if(definition.getPropagationBehavior() == 0 || definition.getPropagationBehavior() == 3 || definition.getPropagationBehavior() == 6)
        {
            SuspendedResourcesHolder suspendedResources = suspend(null);
            if(debugEnabled)
                logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition);
            try
            {
                doBegin(transaction, definition);
            }
            catch(RuntimeException ex)
            {
                resume(null, suspendedResources);
                throw ex;
            }
            catch(Error err)
            {
                resume(null, suspendedResources);
                throw err;
            }
            boolean newSynchronization = getTransactionSynchronization() != 2;
            return newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
        } else
        {
            boolean newSynchronization = getTransactionSynchronization() == 0;
            return newTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null);
        }
    }

    private TransactionStatus handleExistingTransaction(TransactionDefinition definition, Object transaction, boolean debugEnabled)
        throws TransactionException
    {
        if(definition.getPropagationBehavior() == 5)
            throw new IllegalTransactionStateException("Existing transaction found for transaction marked with propagation 'never'");
        if(definition.getPropagationBehavior() == 4)
        {
            if(debugEnabled)
                logger.debug("Suspending current transaction");
            Object suspendedResources = suspend(transaction);
            boolean newSynchronization = getTransactionSynchronization() == 0;
            return newTransactionStatus(definition, null, false, newSynchronization, debugEnabled, suspendedResources);
        }
        if(definition.getPropagationBehavior() == 3)
        {
            if(debugEnabled)
                logger.debug("Suspending current transaction, creating new transaction with name [" + definition.getName() + "]");
            SuspendedResourcesHolder suspendedResources = suspend(transaction);
            try
            {
                doBegin(transaction, definition);
            }
            catch(RuntimeException beginEx)
            {
                resumeAfterBeginException(transaction, suspendedResources, beginEx);
                throw beginEx;
            }
            catch(Error beginErr)
            {
                resumeAfterBeginException(transaction, suspendedResources, beginErr);
                throw beginErr;
            }
            boolean newSynchronization = getTransactionSynchronization() != 2;
            return newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
        }
        boolean newSynchronization;
        if(definition.getPropagationBehavior() == 6)
        {
            if(!isNestedTransactionAllowed())
                throw new NestedTransactionNotSupportedException("Transaction manager does not allow nested transactions by default - specify 'nestedTransactionAllowed' property with value 'true'");
            if(debugEnabled)
                logger.debug("Creating nested transaction with name [" + definition.getName() + "]");
            if(useSavepointForNestedTransaction())
            {
                DefaultTransactionStatus status = newTransactionStatus(definition, transaction, false, false, debugEnabled, null);
                status.createAndHoldSavepoint();
                return status;
            } else
            {
                doBegin(transaction, definition);
                newSynchronization = getTransactionSynchronization() != 2;
                return newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, null);
            }
        }
        if(debugEnabled)
            logger.debug("Participating in existing transaction");
        if(isValidateExistingTransaction())
        {
            if(definition.getIsolationLevel() != -1)
            {
                Integer currentIsolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
                if(currentIsolationLevel == null || currentIsolationLevel.intValue() != definition.getIsolationLevel())
                {
                    Constants isoConstants = DefaultTransactionDefinition.constants;
                    throw new IllegalTransactionStateException("Participating transaction with definition [" + definition + "] specifies isolation level which is incompatible with existing transaction: " + (currentIsolationLevel == null ? "(unknown)" : isoConstants.toCode(currentIsolationLevel, "ISOLATION_")));
                }
            }
            if(!definition.isReadOnly() && TransactionSynchronizationManager.isCurrentTransactionReadOnly())
                throw new IllegalTransactionStateException("Participating transaction with definition [" + definition + "] is not marked as read-only but existing transaction is");
        }
        currentIsolationLevel = getTransactionSynchronization() == 2 ? 0 : 1;
        return newTransactionStatus(definition, transaction, false, currentIsolationLevel, debugEnabled, null);
    }

    protected DefaultTransactionStatus newTransactionStatus(TransactionDefinition definition, Object transaction, boolean newTransaction, boolean newSynchronization, boolean debug, Object suspendedResources)
    {
        boolean actualNewSynchronization = newSynchronization && !TransactionSynchronizationManager.isSynchronizationActive();
        if(actualNewSynchronization)
        {
            TransactionSynchronizationManager.setActualTransactionActive(transaction != null);
            TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(definition.getIsolationLevel() == -1 ? null : new Integer(definition.getIsolationLevel()));
            TransactionSynchronizationManager.setCurrentTransactionReadOnly(definition.isReadOnly());
            TransactionSynchronizationManager.setCurrentTransactionName(definition.getName());
            TransactionSynchronizationManager.initSynchronization();
        }
        return new DefaultTransactionStatus(transaction, newTransaction, actualNewSynchronization, definition.isReadOnly(), debug, suspendedResources);
    }

    protected int determineTimeout(TransactionDefinition definition)
    {
        if(definition.getTimeout() != -1)
            return definition.getTimeout();
        else
            return defaultTimeout;
    }

    protected final SuspendedResourcesHolder suspend(Object transaction)
        throws TransactionException
    {
        if(TransactionSynchronizationManager.isSynchronizationActive())
        {
            List suspendedSynchronizations = doSuspendSynchronization();
            try
            {
                Object suspendedResources = null;
                if(transaction != null)
                    suspendedResources = doSuspend(transaction);
                String name = TransactionSynchronizationManager.getCurrentTransactionName();
                TransactionSynchronizationManager.setCurrentTransactionName(null);
                boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();
                TransactionSynchronizationManager.setCurrentTransactionReadOnly(false);
                Integer isolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
                TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(null);
                boolean wasActive = TransactionSynchronizationManager.isActualTransactionActive();
                TransactionSynchronizationManager.setActualTransactionActive(false);
                return new SuspendedResourcesHolder(suspendedResources, suspendedSynchronizations, name, readOnly, isolationLevel, wasActive);
            }
            catch(RuntimeException ex)
            {
                doResumeSynchronization(suspendedSynchronizations);
                throw ex;
            }
            catch(Error err)
            {
                doResumeSynchronization(suspendedSynchronizations);
                throw err;
            }
        }
        if(transaction != null)
        {
            Object suspendedResources = doSuspend(transaction);
            return new SuspendedResourcesHolder(suspendedResources);
        } else
        {
            return null;
        }
    }

    protected final void resume(Object transaction, SuspendedResourcesHolder resourcesHolder)
        throws TransactionException
    {
        if(resourcesHolder != null)
        {
            Object suspendedResources = resourcesHolder.suspendedResources;
            if(suspendedResources != null)
                doResume(transaction, suspendedResources);
            List suspendedSynchronizations = resourcesHolder.suspendedSynchronizations;
            if(suspendedSynchronizations != null)
            {
                TransactionSynchronizationManager.setActualTransactionActive(resourcesHolder.wasActive);
                TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(resourcesHolder.isolationLevel);
                TransactionSynchronizationManager.setCurrentTransactionReadOnly(resourcesHolder.readOnly);
                TransactionSynchronizationManager.setCurrentTransactionName(resourcesHolder.name);
                doResumeSynchronization(suspendedSynchronizations);
            }
        }
    }

    private void resumeAfterBeginException(Object transaction, SuspendedResourcesHolder suspendedResources, Throwable beginEx)
    {
        String exMessage = "Inner transaction begin exception overridden by outer transaction resume exception";
        try
        {
            resume(transaction, suspendedResources);
        }
        catch(RuntimeException resumeEx)
        {
            logger.error(exMessage, beginEx);
            throw resumeEx;
        }
        catch(Error resumeErr)
        {
            logger.error(exMessage, beginEx);
            throw resumeErr;
        }
    }

    private List doSuspendSynchronization()
    {
        List suspendedSynchronizations = TransactionSynchronizationManager.getSynchronizations();
        for(Iterator it = suspendedSynchronizations.iterator(); it.hasNext(); ((TransactionSynchronization)it.next()).suspend());
        TransactionSynchronizationManager.clearSynchronization();
        return suspendedSynchronizations;
    }

    private void doResumeSynchronization(List suspendedSynchronizations)
    {
        TransactionSynchronizationManager.initSynchronization();
        TransactionSynchronization synchronization;
        for(Iterator it = suspendedSynchronizations.iterator(); it.hasNext(); TransactionSynchronizationManager.registerSynchronization(synchronization))
        {
            synchronization = (TransactionSynchronization)it.next();
            synchronization.resume();
        }

    }

    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");
            else
                return;
        } else
        {
            processCommit(defStatus);
            return;
        }
    }

    private void processCommit(DefaultTransactionStatus status)
        throws TransactionException
    {
        boolean beforeCompletionInvoked = false;
        try
        {
            prepareForCommit(status);
            triggerBeforeCommit(status);
            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, 1);
            throw ex;
        }
        catch(TransactionException ex)
        {
            if(isRollbackOnCommitFailure())
                doRollbackOnCommitException(status, ex);
            else
                triggerAfterCompletion(status, 2);
            throw ex;
        }
        catch(RuntimeException ex)
        {
            if(!beforeCompletionInvoked)
                triggerBeforeCompletion(status);
            doRollbackOnCommitException(status, ex);
            throw ex;
        }
        catch(Error err)
        {
            if(!beforeCompletionInvoked)
                triggerBeforeCompletion(status);
            doRollbackOnCommitException(status, err);
            throw err;
        }
        triggerAfterCommit(status);
        triggerAfterCompletion(status, 0);
        break MISSING_BLOCK_LABEL_217;
        Exception exception;
        exception;
        triggerAfterCompletion(status, 0);
        throw exception;
        cleanupAfterCompletion(status);
        break MISSING_BLOCK_LABEL_235;
        Exception exception1;
        exception1;
        cleanupAfterCompletion(status);
        throw exception1;
    }

    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");
        } else
        {
            DefaultTransactionStatus defStatus = (DefaultTransactionStatus)status;
            processRollback(defStatus);
            return;
        }
    }

    private void processRollback(DefaultTransactionStatus status)
    {
        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
            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");
            }
        }
        catch(RuntimeException ex)
        {
            triggerAfterCompletion(status, 2);
            throw ex;
        }
        catch(Error err)
        {
            triggerAfterCompletion(status, 2);
            throw err;
        }
        triggerAfterCompletion(status, 1);
        cleanupAfterCompletion(status);
        break MISSING_BLOCK_LABEL_197;
        Exception exception;
        exception;
        cleanupAfterCompletion(status);
        throw exception;
    }

    private void doRollbackOnCommitException(DefaultTransactionStatus status, Throwable ex)
        throws TransactionException
    {
        try
        {
            if(status.isNewTransaction())
            {
                if(status.isDebug())
                    logger.debug("Initiating transaction rollback after commit exception", ex);
                doRollback(status);
            } else
            if(status.hasTransaction() && isGlobalRollbackOnParticipationFailure())
            {
                if(status.isDebug())
                    logger.debug("Marking existing transaction as rollback-only after commit exception", ex);
                doSetRollbackOnly(status);
            }
        }
        catch(RuntimeException rbex)
        {
            logger.error("Commit exception overridden by rollback exception", ex);
            triggerAfterCompletion(status, 2);
            throw rbex;
        }
        catch(Error rberr)
        {
            logger.error("Commit exception overridden by rollback exception", ex);
            triggerAfterCompletion(status, 2);
            throw rberr;
        }
        triggerAfterCompletion(status, 1);
    }

    protected final void triggerBeforeCommit(DefaultTransactionStatus status)
    {
        if(status.isNewSynchronization())
        {
            if(status.isDebug())
                logger.trace("Triggering beforeCommit synchronization");
            TransactionSynchronizationUtils.triggerBeforeCommit(status.isReadOnly());
        }
    }

    protected final void triggerBeforeCompletion(DefaultTransactionStatus status)
    {
        if(status.isNewSynchronization())
        {
            if(status.isDebug())
                logger.trace("Triggering beforeCompletion synchronization");
            TransactionSynchronizationUtils.triggerBeforeCompletion();
        }
    }

    private void triggerAfterCommit(DefaultTransactionStatus status)
    {
        if(status.isNewSynchronization())
        {
            if(status.isDebug())
                logger.trace("Triggering afterCommit synchronization");
            TransactionSynchronizationUtils.triggerAfterCommit();
        }
    }

    private void triggerAfterCompletion(DefaultTransactionStatus status, int completionStatus)
    {
        if(status.isNewSynchronization())
        {
            List synchronizations = TransactionSynchronizationManager.getSynchronizations();
            if(!status.hasTransaction() || status.isNewTransaction())
            {
                if(status.isDebug())
                    logger.trace("Triggering afterCompletion synchronization");
                invokeAfterCompletion(synchronizations, completionStatus);
            } else
            {
                registerAfterCompletionWithExistingTransaction(status.getTransaction(), synchronizations);
            }
        }
    }

    protected final void invokeAfterCompletion(List synchronizations, int completionStatus)
    {
        TransactionSynchronizationUtils.invokeAfterCompletion(synchronizations, completionStatus);
    }

    private void cleanupAfterCompletion(DefaultTransactionStatus status)
    {
        status.setCompleted();
        if(status.isNewSynchronization())
            TransactionSynchronizationManager.clear();
        if(status.isNewTransaction())
            doCleanupAfterCompletion(status.getTransaction());
        if(status.getSuspendedResources() != null)
        {
            if(status.isDebug())
                logger.debug("Resuming suspended transaction");
            resume(status.getTransaction(), (SuspendedResourcesHolder)status.getSuspendedResources());
        }
    }

DataSourceTransactionManager

protected Object doGetTransaction()
    {
        DataSourceTransactionObject txObject = new DataSourceTransactionObject();
        txObject.setSavepointAllowed(isNestedTransactionAllowed());
        ConnectionHolder conHolder = (ConnectionHolder)TransactionSynchronizationManager.getResource(dataSource);
        txObject.setConnectionHolder(conHolder, false);
        return txObject;
    }

    protected boolean isExistingTransaction(Object transaction)
    {
        DataSourceTransactionObject txObject = (DataSourceTransactionObject)transaction;
        return txObject.getConnectionHolder() != null && txObject.getConnectionHolder().isTransactionActive();
    }

    protected void doBegin(Object transaction, TransactionDefinition definition)
    {
        DataSourceTransactionObject txObject = (DataSourceTransactionObject)transaction;
        Connection con = null;
        try
        {
            if(txObject.getConnectionHolder() == null || txObject.getConnectionHolder().isSynchronizedWithTransaction())
            {
                Connection newCon = dataSource.getConnection();
                if(logger.isDebugEnabled())
                    logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");
                txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
            }
            txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
            con = txObject.getConnectionHolder().getConnection();
            Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
            txObject.setPreviousIsolationLevel(previousIsolationLevel);
            if(con.getAutoCommit())
            {
                txObject.setMustRestoreAutoCommit(true);
                if(logger.isDebugEnabled())
                    logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
                con.setAutoCommit(false);
            }
            txObject.getConnectionHolder().setTransactionActive(true);
            int timeout = determineTimeout(definition);
            if(timeout != -1)
                txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
            if(txObject.isNewConnectionHolder())
                TransactionSynchronizationManager.bindResource(getDataSource(), txObject.getConnectionHolder());
        }
        catch(SQLException ex)
        {
            DataSourceUtils.releaseConnection(con, dataSource);
            throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex);
        }
    }

    protected Object doSuspend(Object transaction)
    {
        DataSourceTransactionObject txObject = (DataSourceTransactionObject)transaction;
        txObject.setConnectionHolder(null);
        ConnectionHolder conHolder = (ConnectionHolder)TransactionSynchronizationManager.unbindResource(dataSource);
        return conHolder;
    }

    protected void doResume(Object transaction, Object suspendedResources)
    {
        ConnectionHolder conHolder = (ConnectionHolder)suspendedResources;
        TransactionSynchronizationManager.bindResource(dataSource, conHolder);
    }

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

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

    protected void doSetRollbackOnly(DefaultTransactionStatus status)
    {
        DataSourceTransactionObject txObject = (DataSourceTransactionObject)status.getTransaction();
        if(status.isDebug())
            logger.debug("Setting JDBC transaction [" + txObject.getConnectionHolder().getConnection() + "] rollback-only");
        txObject.setRollbackOnly();
    }

    protected void doCleanupAfterCompletion(Object transaction)
    {
        DataSourceTransactionObject txObject = (DataSourceTransactionObject)transaction;
        if(txObject.isNewConnectionHolder())
            TransactionSynchronizationManager.unbindResource(dataSource);
        Connection con = txObject.getConnectionHolder().getConnection();
        try
        {
            if(txObject.isMustRestoreAutoCommit())
                con.setAutoCommit(true);
            DataSourceUtils.resetConnectionAfterTransaction(con, txObject.getPreviousIsolationLevel());
        }
        catch(Throwable ex)
        {
            logger.debug("Could not reset JDBC Connection after transaction", ex);
        }
        if(txObject.isNewConnectionHolder())
        {
            if(logger.isDebugEnabled())
                logger.debug("Releasing JDBC Connection [" + con + "] after transaction");
            DataSourceUtils.releaseConnection(con, dataSource);
        }
        txObject.getConnectionHolder().clear();
    }

    private DataSource dataSource;
}

 HibernateTransactionManager

原文地址:https://www.cnblogs.com/wangjianbg/p/3449521.html