Introduce SessionSynchronization.NEVER to disable transactional participation.

SessionSynchronization.NEVER bypasses all transactional integration in cases where applications do not want to make use of transactions so that transaction inspection overhead is avoided.

Closes: #3760
Original Pull Request: #3809
This commit is contained in:
Mark Paluch
2021-09-08 10:03:45 +02:00
committed by Christoph Strobl
parent 9014f770d8
commit 8fb0e1326b
5 changed files with 61 additions and 4 deletions

View File

@@ -104,7 +104,8 @@ public class MongoDatabaseUtils {
Assert.notNull(factory, "Factory must not be null!");
if (!TransactionSynchronizationManager.isSynchronizationActive()) {
if (sessionSynchronization == SessionSynchronization.NEVER
|| !TransactionSynchronizationManager.isSynchronizationActive()) {
return StringUtils.hasText(dbName) ? factory.getMongoDatabase(dbName) : factory.getMongoDatabase();
}

View File

@@ -138,6 +138,10 @@ public class ReactiveMongoDatabaseUtils {
Assert.notNull(factory, "DatabaseFactory must not be null!");
if (sessionSynchronization == SessionSynchronization.NEVER) {
return getMongoDatabaseOrDefault(dbName, factory);
}
return TransactionSynchronizationManager.forCurrentTransaction()
.filter(TransactionSynchronizationManager::isSynchronizationActive) //
.flatMap(synchronizationManager -> {

View File

@@ -15,13 +15,20 @@
*/
package org.springframework.data.mongodb;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.ReactiveMongoTemplate;
/**
* {@link SessionSynchronization} is used along with {@link org.springframework.data.mongodb.core.MongoTemplate} to
* define in which type of transactions to participate if any.
* {@link SessionSynchronization} is used along with {@code MongoTemplate} to define in which type of transactions to
* participate if any.
*
* @author Christoph Strobl
* @author Mark Paluch
* @since 2.1
* @see MongoTemplate#setSessionSynchronization(SessionSynchronization)
* @see MongoDatabaseUtils#getDatabase(MongoDatabaseFactory, SessionSynchronization)
* @see ReactiveMongoTemplate#setSessionSynchronization(SessionSynchronization)
* @see ReactiveMongoDatabaseUtils#getDatabase(ReactiveMongoDatabaseFactory, SessionSynchronization)
*/
public enum SessionSynchronization {
@@ -34,5 +41,12 @@ public enum SessionSynchronization {
/**
* Synchronize with native MongoDB transactions initiated via {@link MongoTransactionManager}.
*/
ON_ACTUAL_TRANSACTION;
ON_ACTUAL_TRANSACTION,
/**
* Do not participate in ongoing transactions.
*
* @since 3.2.5
*/
NEVER;
}

View File

@@ -109,6 +109,30 @@ class MongoDatabaseUtilsUnitTests {
verify(dbFactory, never()).withSession(any(ClientSession.class));
}
@Test // GH-3760
void shouldJustReturnDatabaseIfSessionSynchronizationDisabled() throws Exception {
when(dbFactory.getMongoDatabase()).thenReturn(db);
JtaTransactionManager txManager = new JtaTransactionManager(userTransaction);
TransactionTemplate txTemplate = new TransactionTemplate(txManager);
txTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
MongoDatabaseUtils.getDatabase(dbFactory, SessionSynchronization.NEVER);
assertThat(TransactionSynchronizationManager.hasResource(dbFactory)).isFalse();
}
});
verify(userTransaction).getStatus();
verifyNoMoreInteractions(userTransaction);
verifyNoInteractions(session);
}
@Test // DATAMONGO-1920
void shouldParticipateInOngoingJtaTransactionWithCommitWhenSessionSychronizationIsAny() throws Exception {

View File

@@ -88,6 +88,20 @@ class ReactiveMongoDatabaseUtilsUnitTests {
}).as(StepVerifier::create).expectNext(true).verifyComplete();
}
@Test // GH-3760
void shouldJustReturnDatabaseIfSessionSynchronizationDisabled() {
when(databaseFactory.getMongoDatabase()).thenReturn(Mono.just(db));
ReactiveMongoDatabaseUtils.getDatabase(databaseFactory, SessionSynchronization.NEVER) //
.as(StepVerifier::create) //
.expectNextCount(1) //
.verifyComplete();
verify(databaseFactory, never()).getSession(any());
verify(databaseFactory, never()).withSession(any(ClientSession.class));
}
@Test // DATAMONGO-2265
void shouldNotStartSessionWhenNoTransactionOngoing() {