Expose savepoint callbacks on TransactionSynchronization
Closes gh-30509
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -138,14 +138,19 @@ public abstract class AbstractTransactionStatus implements TransactionStatus {
|
||||
* Create a savepoint and hold it for the transaction.
|
||||
* @throws org.springframework.transaction.NestedTransactionNotSupportedException
|
||||
* if the underlying transaction does not support savepoints
|
||||
* @see SavepointManager#createSavepoint
|
||||
*/
|
||||
public void createAndHoldSavepoint() throws TransactionException {
|
||||
setSavepoint(getSavepointManager().createSavepoint());
|
||||
Object savepoint = getSavepointManager().createSavepoint();
|
||||
TransactionSynchronizationUtils.triggerSavepoint(savepoint);
|
||||
setSavepoint(savepoint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Roll back to the savepoint that is held for the transaction
|
||||
* and release the savepoint right afterwards.
|
||||
* @see SavepointManager#rollbackToSavepoint
|
||||
* @see SavepointManager#releaseSavepoint
|
||||
*/
|
||||
public void rollbackToHeldSavepoint() throws TransactionException {
|
||||
Object savepoint = getSavepoint();
|
||||
@@ -153,6 +158,7 @@ public abstract class AbstractTransactionStatus implements TransactionStatus {
|
||||
throw new TransactionUsageException(
|
||||
"Cannot roll back to savepoint - no savepoint associated with current transaction");
|
||||
}
|
||||
TransactionSynchronizationUtils.triggerSavepointRollback(savepoint);
|
||||
getSavepointManager().rollbackToSavepoint(savepoint);
|
||||
getSavepointManager().releaseSavepoint(savepoint);
|
||||
setSavepoint(null);
|
||||
@@ -160,6 +166,7 @@ public abstract class AbstractTransactionStatus implements TransactionStatus {
|
||||
|
||||
/**
|
||||
* Release the savepoint that is held for the transaction.
|
||||
* @see SavepointManager#releaseSavepoint
|
||||
*/
|
||||
public void releaseHeldSavepoint() throws TransactionException {
|
||||
Object savepoint = getSavepoint();
|
||||
@@ -184,7 +191,9 @@ public abstract class AbstractTransactionStatus implements TransactionStatus {
|
||||
*/
|
||||
@Override
|
||||
public Object createSavepoint() throws TransactionException {
|
||||
return getSavepointManager().createSavepoint();
|
||||
Object savepoint = getSavepointManager().createSavepoint();
|
||||
TransactionSynchronizationUtils.triggerSavepoint(savepoint);
|
||||
return savepoint;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -195,6 +204,7 @@ public abstract class AbstractTransactionStatus implements TransactionStatus {
|
||||
*/
|
||||
@Override
|
||||
public void rollbackToSavepoint(Object savepoint) throws TransactionException {
|
||||
TransactionSynchronizationUtils.triggerSavepointRollback(savepoint);
|
||||
getSavepointManager().rollbackToSavepoint(savepoint);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -88,6 +88,34 @@ public interface TransactionSynchronization extends Ordered, Flushable {
|
||||
default void flush() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked on creation of a new savepoint, either when a nested transaction
|
||||
* is started against an existing transaction or on a programmatic savepoint
|
||||
* via {@link org.springframework.transaction.TransactionStatus}.
|
||||
* <p>This synchronization callback is invoked right <i>after</i> the creation
|
||||
* of the resource savepoint, with the given savepoint object already active.
|
||||
* @param savepoint the associated savepoint object (primarily as a key for
|
||||
* identifying the savepoint but also castable to the resource savepoint type)
|
||||
* @since 6.2
|
||||
* @see org.springframework.transaction.SavepointManager#createSavepoint
|
||||
* @see org.springframework.transaction.TransactionDefinition#PROPAGATION_NESTED
|
||||
*/
|
||||
default void savepoint(Object savepoint) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked in case of a rollback to the previously created savepoint.
|
||||
* <p>This synchronization callback is invoked right <i>before</i> the rollback
|
||||
* of the resource savepoint, with the given savepoint object still active.
|
||||
* @param savepoint the associated savepoint object (primarily as a key for
|
||||
* identifying the savepoint but also castable to the resource savepoint type)
|
||||
* @since 6.2
|
||||
* @see #savepoint
|
||||
* @see org.springframework.transaction.SavepointManager#rollbackToSavepoint
|
||||
*/
|
||||
default void savepointRollback(Object savepoint) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked before transaction commit (before "beforeCompletion").
|
||||
* Can e.g. flush transactional O/R Mapping sessions to the database.
|
||||
|
||||
@@ -81,8 +81,38 @@ public abstract class TransactionSynchronizationUtils {
|
||||
* @see TransactionSynchronization#flush()
|
||||
*/
|
||||
public static void triggerFlush() {
|
||||
for (TransactionSynchronization synchronization : TransactionSynchronizationManager.getSynchronizations()) {
|
||||
synchronization.flush();
|
||||
if (TransactionSynchronizationManager.isSynchronizationActive()) {
|
||||
for (TransactionSynchronization synchronization : TransactionSynchronizationManager.getSynchronizations()) {
|
||||
synchronization.flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger {@code flush} callbacks on all currently registered synchronizations.
|
||||
* @throws RuntimeException if thrown by a {@code savepoint} callback
|
||||
* @since 6.2
|
||||
* @see TransactionSynchronization#savepoint
|
||||
*/
|
||||
static void triggerSavepoint(Object savepoint) {
|
||||
if (TransactionSynchronizationManager.isSynchronizationActive()) {
|
||||
for (TransactionSynchronization synchronization : TransactionSynchronizationManager.getSynchronizations()) {
|
||||
synchronization.savepoint(savepoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger {@code flush} callbacks on all currently registered synchronizations.
|
||||
* @throws RuntimeException if thrown by a {@code savepointRollback} callback
|
||||
* @since 6.2
|
||||
* @see TransactionSynchronization#savepointRollback
|
||||
*/
|
||||
static void triggerSavepointRollback(Object savepoint) {
|
||||
if (TransactionSynchronizationManager.isSynchronizationActive()) {
|
||||
for (TransactionSynchronization synchronization : TransactionSynchronizationManager.getSynchronizations()) {
|
||||
synchronization.savepointRollback(savepoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user