📄 abstractplatformtransactionmanager.java
字号:
* <p>The result will be evaluated according to the specified propagation
* behavior for the new transaction. An existing transaction might get
* suspended (in case of PROPAGATION_REQUIRES_NEW), or the new transaction
* might participate in the existing one (in case of PROPAGATION_REQUIRED).
* <p>Default implementation returns false, assuming that detection of or
* participating in existing transactions is generally not supported.
* Subclasses are of course encouraged to provide such support.
* @param transaction transaction object returned by doGetTransaction
* @return if there is an existing transaction
* @throws TransactionException in case of system errors
* @see #doGetTransaction
*/
protected boolean isExistingTransaction(Object transaction) throws TransactionException {
return false;
}
/**
* Return whether to use a savepoint for a nested transaction.
* <p>Default is <code>true</code>, which causes delegation to DefaultTransactionStatus
* for creating and holding a savepoint. If the transaction object does not implement
* the SavepointManager interface, a NestedTransactionNotSupportedException will be
* thrown. Else, the SavepointManager will be asked to create a new savepoint to
* demarcate the start of the nested transaction.
* <p>Subclasses can override this to return <code>false</code>, causing a further
* call to <code>doBegin</code> - within the context of an already existing transaction.
* The <code>doBegin</code> implementation needs to handle this accordingly in such
* a scenario. This is appropriate for JTA, for example.
* @see DefaultTransactionStatus#createAndHoldSavepoint
* @see DefaultTransactionStatus#rollbackToHeldSavepoint
* @see DefaultTransactionStatus#releaseHeldSavepoint
* @see #doBegin
*/
protected boolean useSavepointForNestedTransaction() {
return true;
}
/**
* Begin a new transaction with semantics according to the given transaction
* definition. Does not have to care about applying the propagation behavior,
* as this has already been handled by this abstract manager.
* <p>This method gets called when the transaction manager has decided to actually
* start a new transaction. Either there wasn't any transaction before, or the
* previous transaction has been suspended.
* <p>A special scenario is a nested transaction without savepoint: If
* <code>useSavepointForNestedTransaction()</code> returns "false", this method
* will be called to start a nested transaction when necessary. In such a context,
* there will be an active transaction: The implementation of this method has
* to detect this and start an appropriate nested transaction.
* @param transaction transaction object returned by <code>doGetTransaction</code>
* @param definition TransactionDefinition instance, describing propagation
* behavior, isolation level, read-only flag, timeout, and transaction name
* @throws TransactionException in case of creation or system errors
*/
protected abstract void doBegin(Object transaction, TransactionDefinition definition)
throws TransactionException;
/**
* Suspend the resources of the current transaction.
* Transaction synchronization will already have been suspended.
* <p>Default implementation throws a TransactionSuspensionNotSupportedException,
* assuming that transaction suspension is generally not supported.
* @param transaction transaction object returned by <code>doGetTransaction</code>
* @return an object that holds suspended resources
* (will be kept unexamined for passing it into doResume)
* @throws org.springframework.transaction.TransactionSuspensionNotSupportedException
* if suspending is not supported by the transaction manager implementation
* @throws TransactionException in case of system errors
* @see #doResume
*/
protected Object doSuspend(Object transaction) throws TransactionException {
throw new TransactionSuspensionNotSupportedException(
"Transaction manager [" + getClass().getName() + "] does not support transaction suspension");
}
/**
* Resume the resources of the current transaction.
* Transaction synchronization will be resumed afterwards.
* <p>Default implementation throws a TransactionSuspensionNotSupportedException,
* assuming that transaction suspension is generally not supported.
* @param transaction transaction object returned by <code>doGetTransaction</code>
* @param suspendedResources the object that holds suspended resources,
* as returned by doSuspend
* @throws org.springframework.transaction.TransactionSuspensionNotSupportedException
* if resuming is not supported by the transaction manager implementation
* @throws TransactionException in case of system errors
* @see #doSuspend
*/
protected void doResume(Object transaction, Object suspendedResources) throws TransactionException {
throw new TransactionSuspensionNotSupportedException(
"Transaction manager [" + getClass().getName() + "] does not support transaction suspension");
}
/**
* Return whether to call <code>doCommit</code> on a transaction
* that has been marked as rollback-only in a global fashion.
* <p>Does not apply if an application locally sets the transaction to
* rollback-only via the TransactionStatus, but only to the transaction
* itself being marked as rollback-only by the transaction coordinator.
* <p>Default is "false": Local transaction strategies usually don't
* hold the rollback-only marker in the transaction itself, therefore
* they can't handle rollback-only transactions in a special manner.
* Hence, AbstractPlatformTransactionManager will trigger a rollback
* in that case, throwing an UnexpectedRollbackException afterwards.
* <p>Override this to return "true" if the concrete transaction manager
* expects a <code>doCommit</code> call even for a rollback-only transaction,
* allowing for special handling there. This will, for example, be the case
* for JTA, where <code>UserTransaction.commit</code> will check the read-only
* flag itself and throw a corresponding RollbackException, which might
* include the specific reason (such as a transaction timeout).
* <p>If this method returns "true" but the <code>doCommit</code>
* implementation does not throw an exception, this transaction manager
* will throw an UnexpectedRollbackException itself. This should not be the
* typical case; it is mainly checked to cover misbehaving JTA providers that
* silently roll back even when the rollback has not been requested by the user.
* @see #doCommit
* @see DefaultTransactionStatus#isGlobalRollbackOnly()
* @see DefaultTransactionStatus#isLocalRollbackOnly()
* @see org.springframework.transaction.TransactionStatus#setRollbackOnly()
* @see org.springframework.transaction.UnexpectedRollbackException
* @see javax.transaction.UserTransaction#commit()
* @see javax.transaction.RollbackException
*/
protected boolean shouldCommitOnGlobalRollbackOnly() {
return false;
}
/**
* Perform an actual commit of the given transaction.
* <p>An implementation does not need to check the "new transaction" flag
* or the rollback-only flag; this will already have been handled before.
* Usually, a straight commit will be performed on the transaction object
* contained in the passed-in status.
* @param status the status representation of the transaction
* @throws TransactionException in case of commit or system errors
* @see DefaultTransactionStatus#getTransaction
*/
protected abstract void doCommit(DefaultTransactionStatus status) throws TransactionException;
/**
* Perform an actual rollback of the given transaction.
* <p>An implementation does not need to check the "new transaction" flag;
* this will already have been handled before. Usually, a straight rollback
* will be performed on the transaction object contained in the passed-in status.
* @param status the status representation of the transaction
* @throws TransactionException in case of system errors
* @see DefaultTransactionStatus#getTransaction
*/
protected abstract void doRollback(DefaultTransactionStatus status) throws TransactionException;
/**
* Set the given transaction rollback-only. Only called on rollback
* if the current transaction participates in an existing one.
* <p>Default implementation throws an IllegalTransactionStateException,
* assuming that participating in existing transactions is generally not
* supported. Subclasses are of course encouraged to provide such support.
* @param status the status representation of the transaction
* @throws TransactionException in case of system errors
*/
protected void doSetRollbackOnly(DefaultTransactionStatus status) throws TransactionException {
throw new IllegalTransactionStateException(
"Participating in existing transactions is not supported - when 'isExistingTransaction' " +
"returns true, appropriate 'doSetRollbackOnly' behavior must be provided");
}
/**
* Register the given list of transaction synchronizations with the
* existing transaction.
* <p>Invoked when the control of the Spring transaction manager and thus
* all Spring transaction synchronizations end, without the transaction
* being completed yet. This is for example the case when participating
* in an existing JTA or EJB CMT transaction.
* <p>Default implementation simply invokes the <code>afterCompletion</code>
* methods immediately, passing in "STATUS_UNKNOWN". This is the best we
* can do if there's no chance to determine the actual outcome of the
* outer transaction.
* @param transaction transaction object returned by <code>doGetTransaction</code>
* @param synchronizations List of TransactionSynchronization objects
* @throws TransactionException in case of system errors
* @see #invokeAfterCompletion(java.util.List, int)
* @see TransactionSynchronization#afterCompletion(int)
* @see TransactionSynchronization#STATUS_UNKNOWN
*/
protected void registerAfterCompletionWithExistingTransaction(Object transaction, List synchronizations)
throws TransactionException {
logger.debug("Cannot register Spring after-completion synchronization with existing transaction - " +
"performing Spring after-completion callbacks immediately, with outcome status 'unknown'");
invokeAfterCompletion(synchronizations, TransactionSynchronization.STATUS_UNKNOWN);
}
/**
* Cleanup resources after transaction completion.
* Called after <code>doCommit</code> and <code>doRollback</code> execution,
* on any outcome. Default implementation does nothing.
* <p>Should not throw any exceptions but just issue warnings on errors.
* @param transaction transaction object returned by doGetTransaction
*/
protected void doCleanupAfterCompletion(Object transaction) {
}
//---------------------------------------------------------------------
// Serialization support
//---------------------------------------------------------------------
private void readObject(ObjectInputStream ois) throws IOException {
// Rely on default serialization, just initialize state after deserialization.
try {
ois.defaultReadObject();
}
catch (ClassNotFoundException ex) {
throw new IOException("Failed to deserialize [" + getClass().getName() + "] - " +
"check that Spring transaction libraries are available on the client side: " + ex.getMessage());
}
// Initialize transient fields.
this.logger = LogFactory.getLog(getClass());
}
/**
* Holder for suspended resources.
* Used internally by <code>suspend</code> and <code>resume</code>.
*/
private static class SuspendedResourcesHolder {
private final Object suspendedResources;
private final List suspendedSynchronizations;
private final String name;
private final boolean readOnly;
public SuspendedResourcesHolder(
Object suspendedResources, List suspendedSynchronizations, String name, boolean readOnly) {
this.suspendedResources = suspendedResources;
this.suspendedSynchronizations = suspendedSynchronizations;
this.name = name;
this.readOnly = readOnly;
}
public Object getSuspendedResources() {
return suspendedResources;
}
public List getSuspendedSynchronizations() {
return suspendedSynchronizations;
}
public String getName() {
return name;
}
public boolean isReadOnly() {
return readOnly;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -