📄 abstractplatformtransactionmanager.java
字号:
else if (status.isNewTransaction()) {
logger.debug("Initiating transaction commit");
doCommit(defStatus);
}
}
catch (UnexpectedRollbackException ex) {
// can only be caused by doCommit
triggerAfterCompletion(defStatus, TransactionSynchronization.STATUS_ROLLED_BACK, ex);
throw ex;
}
catch (TransactionException ex) {
// can only be caused by doCommit
if (isRollbackOnCommitFailure()) {
doRollbackOnCommitException(defStatus, ex);
}
else {
triggerAfterCompletion(defStatus, TransactionSynchronization.STATUS_UNKNOWN, ex);
}
throw ex;
}
catch (RuntimeException ex) {
if (!beforeCompletionInvoked) {
triggerBeforeCompletion(defStatus, ex);
}
doRollbackOnCommitException(defStatus, ex);
throw ex;
}
catch (Error err) {
if (!beforeCompletionInvoked) {
triggerBeforeCompletion(defStatus, err);
}
doRollbackOnCommitException(defStatus, err);
throw err;
}
triggerAfterCompletion(defStatus, TransactionSynchronization.STATUS_COMMITTED, null);
}
finally {
cleanupAfterCompletion(defStatus);
}
}
}
/**
* This implementation of rollback handles participating in existing
* transactions. Delegates to doRollback and doSetRollbackOnly.
* @see #doRollback
* @see #doSetRollbackOnly
*/
public final void rollback(TransactionStatus status) throws TransactionException {
DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
try {
try {
triggerBeforeCompletion(defStatus, null);
if (defStatus.hasSavepoint()) {
if (defStatus.isDebug()) {
logger.debug("Rolling back transaction to savepoint");
}
defStatus.rollbackToHeldSavepoint();
}
else if (status.isNewTransaction()) {
logger.debug("Initiating transaction rollback");
doRollback(defStatus);
}
else if (defStatus.getTransaction() != null) {
if (defStatus.isDebug()) {
logger.debug("Setting existing transaction rollback-only");
}
doSetRollbackOnly(defStatus);
}
else {
logger.warn("Should roll back transaction but cannot - no transaction available");
}
}
catch (RuntimeException ex) {
triggerAfterCompletion(defStatus, TransactionSynchronization.STATUS_UNKNOWN, ex);
throw ex;
}
catch (Error err) {
triggerAfterCompletion(defStatus, TransactionSynchronization.STATUS_UNKNOWN, err);
throw err;
}
triggerAfterCompletion(defStatus, TransactionSynchronization.STATUS_ROLLED_BACK, null);
}
finally {
cleanupAfterCompletion(defStatus);
}
}
/**
* Invoke doRollback, handling rollback exceptions properly.
* @param status object representing the transaction
* @param ex the thrown application exception or error
* @throws TransactionException in case of a rollback error
* @see #doRollback
*/
private void doRollbackOnCommitException(DefaultTransactionStatus status, Throwable ex)
throws TransactionException {
try {
if (status.isNewTransaction()) {
if (status.isDebug()) {
logger.debug("Initiating transaction rollback on commit exception", ex);
}
doRollback(status);
}
}
catch (RuntimeException rbex) {
logger.error("Commit exception overridden by rollback exception", ex);
triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN, rbex);
throw rbex;
}
catch (Error rberr) {
logger.error("Commit exception overridden by rollback exception", ex);
triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN, rberr);
throw rberr;
}
triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK, ex);
}
/**
* Trigger beforeCommit callback.
* @param status object representing the transaction
*/
private void triggerBeforeCommit(DefaultTransactionStatus status) {
if (status.isNewSynchronization()) {
logger.debug("Triggering beforeCommit synchronization");
for (Iterator it = TransactionSynchronizationManager.getSynchronizations().iterator(); it.hasNext();) {
TransactionSynchronization synchronization = (TransactionSynchronization) it.next();
synchronization.beforeCommit(status.isReadOnly());
}
}
}
/**
* Trigger beforeCompletion callback.
* @param status object representing the transaction
* @param ex the thrown application exception or error, or null
*/
private void triggerBeforeCompletion(DefaultTransactionStatus status, Throwable ex) {
if (status.isNewSynchronization()) {
logger.debug("Triggering beforeCompletion synchronization");
try {
for (Iterator it = TransactionSynchronizationManager.getSynchronizations().iterator(); it.hasNext();) {
TransactionSynchronization synchronization = (TransactionSynchronization) it.next();
synchronization.beforeCompletion();
}
}
catch (RuntimeException tsex) {
if (ex != null) {
logger.error("Rollback exception overridden by synchronization exception", ex);
}
throw tsex;
}
catch (Error tserr) {
if (ex != null) {
logger.error("Rollback exception overridden by synchronization exception", ex);
}
throw tserr;
}
}
}
/**
* Trigger afterCompletion callback, handling exceptions properly.
* @param status object representing the transaction
* @param completionStatus completion status according to TransactionSynchronization constants
* @param ex the thrown application exception or error, or null
*/
private void triggerAfterCompletion(DefaultTransactionStatus status, int completionStatus, Throwable ex) {
if (status.isNewSynchronization()) {
logger.debug("Triggering afterCompletion synchronization");
try {
for (Iterator it = TransactionSynchronizationManager.getSynchronizations().iterator(); it.hasNext();) {
TransactionSynchronization synchronization = (TransactionSynchronization) it.next();
synchronization.afterCompletion(completionStatus);
}
}
catch (RuntimeException tsex) {
if (ex != null) {
logger.error("Rollback exception overridden by synchronization exception", ex);
}
throw tsex;
}
catch (Error tserr) {
if (ex != null) {
logger.error("Rollback exception overridden by synchronization exception", ex);
}
throw tserr;
}
}
}
/**
* Clean up after completion, clearing synchronization if necessary,
* and invoking doCleanupAfterCompletion.
* @param status object representing the transaction
* @see #doCleanupAfterCompletion
*/
private void cleanupAfterCompletion(DefaultTransactionStatus status) {
if (status.isNewSynchronization()) {
TransactionSynchronizationManager.clearSynchronization();
}
if (status.isNewTransaction() && !status.hasSavepoint()) {
doCleanupAfterCompletion(status.getTransaction());
}
if (status.getSuspendedResources() != null) {
if (status.isDebug()) {
logger.debug("Resuming suspended transaction");
}
resume(status.getTransaction(), status.getSuspendedResources());
}
}
//---------------------------------------------------------------------
// 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());
}
//---------------------------------------------------------------------
// Template methods to be implemented in subclasses
//---------------------------------------------------------------------
/**
* Return a current transaction object, i.e. a JTA UserTransaction.
* @return the current transaction object
* @throws org.springframework.transaction.CannotCreateTransactionException
* if transaction support is not available (e.g. no JTA UserTransaction retrievable from JNDI)
* @throws TransactionException in case of lookup or system errors
*/
protected abstract Object doGetTransaction() throws TransactionException;
/**
* Check if the given transaction object indicates an existing,
* i.e. already begun, transaction.
* @param transaction transaction object returned by doGetTransaction
* @return if there is an existing transaction
* @throws TransactionException in case of system errors
*/
protected abstract boolean isExistingTransaction(Object transaction) throws TransactionException;
/**
* Return whether to use a savepoint for a nested transaction. Default is true,
* which causes delegation to DefaultTransactionStatus for holding a savepoint.
* <p>Subclasses can override this to return false, causing a further
* invocation of doBegin despite an already existing transaction.
* @see DefaultTransactionStatus#createAndHoldSavepoint
* @see DefaultTransactionStatus#rollbackToHeldSavepoint
* @see DefaultTransactionStatus#releaseHeldSavepoint
* @see #doBegin
*/
protected boolean useSavepointForNestedTransaction() {
return true;
}
/**
* Begin a new transaction with the given transaction definition.
* Does not have to care about applying the propagation behavior,
* as this has already been handled by this abstract manager.
* @param transaction transaction object returned by doGetTransaction
* @param definition TransactionDefinition instance, describing
* propagation behavior, isolation level, timeout etc.
* @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.
* @param transaction transaction object returned by doGetTransaction
* @return an object that holds suspended resources
* (will be kept unexamined for passing it into doResume)
* @throws org.springframework.transaction.IllegalTransactionStateException
* if suspending is not supported by the transaction manager implementation
* @throws TransactionException in case of system errors
* @see #doResume
*/
protected abstract Object doSuspend(Object transaction) throws TransactionException;
/**
* Resume the resources of the current transaction.
* Transaction synchronization will be resumed afterwards.
* @param transaction transaction object returned by doGetTransaction
* @param suspendedResources the object that holds suspended resources,
* as returned by doSuspend
* @throws org.springframework.transaction.IllegalTransactionStateException
* if resuming is not supported by the transaction manager implementation
* @throws TransactionException in case of system errors
* @see #doSuspend
*/
protected abstract void doResume(Object transaction, Object suspendedResources)
throws TransactionException;
/**
* Perform an actual commit on the given transaction.
* An implementation does not need to check the rollback-only flag.
* @param status status representation of the transaction
* @throws TransactionException in case of commit or system errors
*/
protected abstract void doCommit(DefaultTransactionStatus status) throws TransactionException;
/**
* Perform an actual rollback on the given transaction.
* An implementation does not need to check the new transaction flag.
* @param status status representation of the transaction
* @throws TransactionException in case of system errors
*/
protected abstract void doRollback(DefaultTransactionStatus status) throws TransactionException;
/**
* Set the given transaction rollback-only. Only called on rollback
* if the current transaction takes part in an existing one.
* @param status status representation of the transaction
* @throws TransactionException in case of system errors
*/
protected abstract void doSetRollbackOnly(DefaultTransactionStatus status) throws TransactionException;
/**
* Cleanup resources after transaction completion.
* Called after doCommit and doRollback execution on any outcome.
* Should not throw any exceptions but just issue warnings on errors.
* <p>Default implementation does nothing.
* @param transaction transaction object returned by doGetTransaction
*/
protected void doCleanupAfterCompletion(Object transaction) {
}
/**
* Holder for suspended resources.
* Used internally by suspend and resume.
* @see #suspend
* @see #resume
*/
private static class SuspendedResourcesHolder {
private final List suspendedSynchronizations;
private final Object suspendedResources;
private SuspendedResourcesHolder(List suspendedSynchronizations, Object suspendedResources) {
this.suspendedSynchronizations = suspendedSynchronizations;
this.suspendedResources = suspendedResources;
}
private List getSuspendedSynchronizations() {
return suspendedSynchronizations;
}
private Object getSuspendedResources() {
return suspendedResources;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -