📄 abstractplatformtransactionmanager.java
字号:
// No existing transaction found -> check propagation behavior to find out how to proceed.
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
throw new IllegalTransactionStateException(
"No existing transaction found for transaction marked with propagation 'mandatory'");
}
else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
Object suspendedResources = suspend(null);
if (debugEnabled) {
logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition);
}
doBegin(transaction, definition);
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
return newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
}
else {
// Create "empty" transaction: no actual transaction, but potentially synchronization.
boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
return newTransactionStatus(definition, null, false, newSynchronization, debugEnabled, null);
}
}
/**
* Create a TransactionStatus for an existing transaction.
*/
private TransactionStatus handleExistingTransaction(
TransactionDefinition definition, Object transaction, boolean debugEnabled)
throws TransactionException {
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
throw new IllegalTransactionStateException(
"Existing transaction found for transaction marked with propagation 'never'");
}
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
if (debugEnabled) {
logger.debug("Suspending current transaction");
}
Object suspendedResources = suspend(transaction);
boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
return newTransactionStatus(
definition, null, false, newSynchronization, debugEnabled, suspendedResources);
}
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
if (debugEnabled) {
logger.debug("Suspending current transaction, creating new transaction with name [" +
definition.getName() + "]");
}
SuspendedResourcesHolder suspendedResources = suspend(transaction);
try {
doBegin(transaction, definition);
}
catch (TransactionException beginEx) {
try {
resume(transaction, suspendedResources);
}
catch (TransactionException resumeEx) {
logger.error(
"Inner transaction begin exception overridden by outer transaction resume exception", beginEx);
throw resumeEx;
}
throw beginEx;
}
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
return newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
}
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
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()) {
// Create savepoint within existing Spring-managed transaction,
// through the SavepointManager API implemented by TransactionStatus.
// Usually uses JDBC 3.0 savepoints. Never activates Spring synchronization.
DefaultTransactionStatus status =
newTransactionStatus(definition, transaction, false, false, debugEnabled, null);
status.createAndHoldSavepoint();
return status;
}
else {
// Nested transaction through nested begin and commit/rollback calls.
// Usually only for JTA: Spring synchronization might get activated here
// in case of a pre-existing JTA transaction.
doBegin(transaction, definition);
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
return newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, null);
}
}
// Assumably PROPAGATION_SUPPORTS.
if (debugEnabled) {
logger.debug("Participating in existing transaction");
}
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
return newTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null);
}
/**
* Create a new TransactionStatus for the given arguments,
* initializing transaction synchronization if appropriate.
*/
private 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.setCurrentTransactionReadOnly(definition.isReadOnly());
TransactionSynchronizationManager.setCurrentTransactionName(definition.getName());
TransactionSynchronizationManager.initSynchronization();
}
return new DefaultTransactionStatus(
transaction, newTransaction, actualNewSynchronization,
definition.isReadOnly(), debug, suspendedResources);
}
/**
* Suspend the given transaction. Suspends transaction synchronization first,
* then delegates to the <code>doSuspend</code> template method.
* @param transaction the current transaction object
* (or <code>null</code> to just suspend active synchronizations, if any)
* @return an object that holds suspended resources
* (or <code>null</code> if neither transaction nor synchronization active)
* @see #doSuspend
* @see #resume
*/
private 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);
TransactionSynchronizationManager.setActualTransactionActive(false);
return new SuspendedResourcesHolder(suspendedResources, suspendedSynchronizations, name, readOnly);
}
catch (TransactionException ex) {
// doSuspend failed - original transaction is still active...
doResumeSynchronization(suspendedSynchronizations);
throw ex;
}
}
else if (transaction != null) {
// Transaction active but no synchronization active.
Object suspendedResources = doSuspend(transaction);
return new SuspendedResourcesHolder(suspendedResources, null, null, false);
}
else {
// Neither transaction nor synchronization active.
return null;
}
}
/**
* Resume the given transaction. Delegates to the <code>doResume</code>
* template method first, then resuming transaction synchronization.
* @param transaction the current transaction object
* @param resourcesHolder the object that holds suspended resources,
* as returned by <code>suspend</code> (or <code>null</code> to just
* resume synchronizations, if any)
* @see #doResume
* @see #suspend
*/
private void resume(Object transaction, SuspendedResourcesHolder resourcesHolder) throws TransactionException {
Object suspendedResources = resourcesHolder.getSuspendedResources();
if (suspendedResources != null) {
doResume(transaction, suspendedResources);
}
List suspendedSynchronizations = resourcesHolder.getSuspendedSynchronizations();
if (suspendedSynchronizations != null) {
TransactionSynchronizationManager.setActualTransactionActive(suspendedResources != null);
TransactionSynchronizationManager.setCurrentTransactionReadOnly(resourcesHolder.isReadOnly());
TransactionSynchronizationManager.setCurrentTransactionName(resourcesHolder.getName());
doResumeSynchronization(suspendedSynchronizations);
}
}
/**
* Suspend all current synchronizations and deactivate transaction
* synchronization for the current thread.
* @return the List of suspended TransactionSynchronization objects
*/
private List doSuspendSynchronization() {
List suspendedSynchronizations = TransactionSynchronizationManager.getSynchronizations();
for (Iterator it = suspendedSynchronizations.iterator(); it.hasNext();) {
((TransactionSynchronization) it.next()).suspend();
}
TransactionSynchronizationManager.clearSynchronization();
return suspendedSynchronizations;
}
/**
* Reactivate transaction synchronization for the current thread
* and resume all given synchronizations.
* @param suspendedSynchronizations List of TransactionSynchronization objects
*/
private void doResumeSynchronization(List suspendedSynchronizations) {
TransactionSynchronizationManager.initSynchronization();
for (Iterator it = suspendedSynchronizations.iterator(); it.hasNext();) {
TransactionSynchronization synchronization = (TransactionSynchronization) it.next();
synchronization.resume();
TransactionSynchronizationManager.registerSynchronization(synchronization);
}
}
/**
* This implementation of commit handles participating in existing
* transactions and programmatic rollback requests.
* Delegates to <code>isRollbackOnly</code>, <code>doCommit</code>
* and <code>rollback</code>.
* @see org.springframework.transaction.TransactionStatus#isRollbackOnly()
* @see #doCommit
* @see #rollback
*/
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);
throw new UnexpectedRollbackException(
"Transaction rolled back because it has been marked as rollback-only");
}
processCommit(defStatus);
}
/**
* Process an actual commit.
* Rollback-only flags have already been checked and applied.
* @param status object representing the transaction
* @throws TransactionException in case of commit failure
*/
private void processCommit(DefaultTransactionStatus status) throws TransactionException {
try {
boolean beforeCompletionInvoked = false;
try {
triggerBeforeCommit(status);
triggerBeforeCompletion(status);
beforeCompletionInvoked = true;
if (status.hasSavepoint()) {
if (status.isDebug()) {
logger.debug("Releasing transaction savepoint");
}
status.releaseHeldSavepoint();
}
else if (status.isNewTransaction()) {
if (status.isDebug()) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -