Consistently release savepoint after nested transaction

Closes gh-31133
This commit is contained in:
Juergen Hoeller
2023-09-11 17:36:00 +02:00
parent 11dc11e989
commit 2880e6fba5
2 changed files with 145 additions and 68 deletions

View File

@@ -337,36 +337,36 @@ public class R2dbcTransactionManager extends AbstractReactiveTransactionManager
return Mono.defer(() -> {
ConnectionFactoryTransactionObject txObject = (ConnectionFactoryTransactionObject) transaction;
if (txObject.hasSavepoint()) {
// Just release the savepoint, keeping the transactional connection.
return txObject.releaseSavepoint();
}
// Remove the connection holder from the context, if exposed.
if (txObject.isNewConnectionHolder()) {
synchronizationManager.unbindResource(obtainConnectionFactory());
}
// Reset connection.
Connection con = txObject.getConnectionHolder().getConnection();
Mono<Void> afterCleanup = Mono.empty();
Mono<Void> releaseConnectionStep = Mono.defer(() -> {
try {
if (txObject.isNewConnectionHolder()) {
if (logger.isDebugEnabled()) {
logger.debug("Releasing R2DBC Connection [" + con + "] after transaction");
}
Mono<Void> releaseMono = ConnectionFactoryUtils.releaseConnection(con, obtainConnectionFactory());
if (logger.isDebugEnabled()) {
releaseMono = releaseMono.doOnError(
ex -> logger.debug(String.format("Error ignored during cleanup: %s", ex)));
}
return releaseMono.onErrorComplete();
try {
if (txObject.isNewConnectionHolder()) {
Connection con = txObject.getConnectionHolder().getConnection();
if (logger.isDebugEnabled()) {
logger.debug("Releasing R2DBC Connection [" + con + "] after transaction");
}
Mono<Void> releaseMono = ConnectionFactoryUtils.releaseConnection(con, obtainConnectionFactory());
if (logger.isDebugEnabled()) {
releaseMono = releaseMono.doOnError(
ex -> logger.debug(String.format("Error ignored during cleanup: %s", ex)));
}
return releaseMono.onErrorComplete();
}
finally {
txObject.getConnectionHolder().clear();
}
return Mono.empty();
});
return afterCleanup.then(releaseConnectionStep);
}
finally {
txObject.getConnectionHolder().clear();
}
return Mono.empty();
});
}
@@ -511,23 +511,36 @@ public class R2dbcTransactionManager extends AbstractReactiveTransactionManager
return (this.connectionHolder != null && this.connectionHolder.isTransactionActive());
}
public boolean hasSavepoint() {
return (this.savepointName != null);
}
public Mono<Void> createSavepoint() {
ConnectionHolder holder = getConnectionHolder();
this.savepointName = holder.nextSavepoint();
return Mono.from(holder.getConnection().createSavepoint(this.savepointName));
String currentSavepoint = holder.nextSavepoint();
this.savepointName = currentSavepoint;
return Mono.from(holder.getConnection().createSavepoint(currentSavepoint));
}
public Mono<Void> releaseSavepoint() {
String currentSavepoint = this.savepointName;
if (currentSavepoint == null) {
return Mono.empty();
}
this.savepointName = null;
return Mono.from(getConnectionHolder().getConnection().releaseSavepoint(currentSavepoint));
}
public Mono<Void> commit() {
Connection connection = getConnectionHolder().getConnection();
return (this.savepointName != null ?
Mono.from(connection.releaseSavepoint(this.savepointName)) :
Mono.from(connection.commitTransaction()));
return (hasSavepoint() ? Mono.empty() :
Mono.from(getConnectionHolder().getConnection().commitTransaction()));
}
public Mono<Void> rollback() {
Connection connection = getConnectionHolder().getConnection();
return (this.savepointName != null ?
Mono.from(connection.rollbackTransactionToSavepoint(this.savepointName)) :
String currentSavepoint = this.savepointName;
return (currentSavepoint != null ?
Mono.from(connection.rollbackTransactionToSavepoint(currentSavepoint)) :
Mono.from(connection.rollbackTransaction()));
}