DATAMONGO-2490 - Fix dbref fetching during ongoing transaction.
Original pull request: #875.
This commit is contained in:
committed by
Mark Paluch
parent
773f20f861
commit
be46540959
@@ -79,7 +79,7 @@ public class MongoDatabaseUtils {
|
||||
* @param factory the {@link MongoDbFactory} to get the {@link MongoDatabase} from.
|
||||
* @return the {@link MongoDatabase} that is potentially associated with a transactional {@link ClientSession}.
|
||||
*/
|
||||
public static MongoDatabase getDatabase(String dbName, MongoDbFactory factory) {
|
||||
public static MongoDatabase getDatabase(@Nullable String dbName, MongoDbFactory factory) {
|
||||
return doGetMongoDatabase(dbName, factory, SessionSynchronization.ON_ACTUAL_TRANSACTION);
|
||||
}
|
||||
|
||||
@@ -88,13 +88,13 @@ public class MongoDatabaseUtils {
|
||||
* <p />
|
||||
* Registers a {@link MongoSessionSynchronization MongoDB specific transaction synchronization} within the current
|
||||
* {@link Thread} if {@link TransactionSynchronizationManager#isSynchronizationActive() synchronization is active}.
|
||||
*
|
||||
*
|
||||
* @param dbName the name of the {@link MongoDatabase} to get.
|
||||
* @param factory the {@link MongoDbFactory} to get the {@link MongoDatabase} from.
|
||||
* @param sessionSynchronization the synchronization to use. Must not be {@literal null}.
|
||||
* @return the {@link MongoDatabase} that is potentially associated with a transactional {@link ClientSession}.
|
||||
*/
|
||||
public static MongoDatabase getDatabase(String dbName, MongoDbFactory factory,
|
||||
public static MongoDatabase getDatabase(@Nullable String dbName, MongoDbFactory factory,
|
||||
SessionSynchronization sessionSynchronization) {
|
||||
return doGetMongoDatabase(dbName, factory, sessionSynchronization);
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ import org.springframework.dao.support.PersistenceExceptionTranslator;
|
||||
import org.springframework.data.mongodb.ClientSessionException;
|
||||
import org.springframework.data.mongodb.LazyLoadingException;
|
||||
import org.springframework.data.mongodb.MongoDbFactory;
|
||||
import org.springframework.data.mongodb.MongoDatabaseUtils;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.objenesis.ObjenesisStd;
|
||||
@@ -497,7 +498,7 @@ public class DefaultDbRefResolver implements DbRefResolver {
|
||||
*/
|
||||
protected MongoCollection<Document> getCollection(DBRef dbref) {
|
||||
|
||||
return (StringUtils.hasText(dbref.getDatabaseName()) ? mongoDbFactory.getDb(dbref.getDatabaseName())
|
||||
: mongoDbFactory.getDb()).getCollection(dbref.getCollectionName(), Document.class);
|
||||
return MongoDatabaseUtils.getDatabase(dbref.getDatabaseName(), mongoDbFactory)
|
||||
.getCollection(dbref.getCollectionName(), Document.class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.junit.Test;
|
||||
import org.junit.rules.TestRule;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
|
||||
import org.springframework.data.mongodb.core.mapping.DBRef;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.data.mongodb.test.util.MongoTestUtils;
|
||||
import org.springframework.data.mongodb.test.util.MongoVersion;
|
||||
@@ -54,6 +55,7 @@ public class ClientSessionTests {
|
||||
|
||||
private static final String DB_NAME = "client-session-tests";
|
||||
private static final String COLLECTION_NAME = "test";
|
||||
private static final String REF_COLLECTION_NAME = "test-with-ref";
|
||||
|
||||
MongoTemplate template;
|
||||
MongoClient client;
|
||||
@@ -154,6 +156,31 @@ public class ClientSessionTests {
|
||||
assertThat(template.exists(query(where("id").is(saved.getId())), SomeDoc.class)).isFalse();
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-2490
|
||||
public void shouldBeAbleToReadDbRefDuringTransaction() {
|
||||
|
||||
SomeDoc ref = new SomeDoc("ref-1", "da value");
|
||||
WithDbRef source = new WithDbRef("source-1", "da source", ref);
|
||||
|
||||
ClientSession session = mongoClient.startSession(ClientSessionOptions.builder().causallyConsistent(true).build());
|
||||
|
||||
assertThat(session.getOperationTime()).isNull();
|
||||
|
||||
session.startTransaction();
|
||||
|
||||
WithDbRef saved = template.withSession(() -> session).execute(action -> {
|
||||
|
||||
template.save(ref);
|
||||
template.save(source);
|
||||
|
||||
return template.findOne(query(where("id").is(source.id)), WithDbRef.class);
|
||||
});
|
||||
|
||||
assertThat(saved.getSomeDocRef()).isEqualTo(ref);
|
||||
|
||||
session.abortTransaction();
|
||||
}
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@org.springframework.data.mongodb.core.mapping.Document(COLLECTION_NAME)
|
||||
@@ -163,4 +190,14 @@ public class ClientSessionTests {
|
||||
String value;
|
||||
}
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@org.springframework.data.mongodb.core.mapping.Document(REF_COLLECTION_NAME)
|
||||
static class WithDbRef {
|
||||
|
||||
@Id String id;
|
||||
String value;
|
||||
@DBRef SomeDoc someDocRef;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import static org.springframework.data.mongodb.test.util.MongoTestUtils.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import org.bson.Document;
|
||||
@@ -175,6 +176,25 @@ public class PersonRepositoryTransactionalTests {
|
||||
assertAfterTransaction(hu).isNotPresent();
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-2490
|
||||
public void shouldBeAbleToReadDbRefDuringTransaction() {
|
||||
|
||||
User rat = new User();
|
||||
rat.setUsername("rat");
|
||||
|
||||
template.save(rat);
|
||||
|
||||
Person elene = new Person("Elene", "Cromwyll", 18);
|
||||
elene.setCoworker(rat);
|
||||
|
||||
repository.save(elene);
|
||||
|
||||
Optional<Person> loaded = repository.findById(elene.getId());
|
||||
assertThat(loaded).isPresent();
|
||||
assertThat(loaded.get().getCoworker()).isNotNull();
|
||||
assertThat(loaded.get().getCoworker().getUsername()).isEqualTo(rat.getUsername());
|
||||
}
|
||||
|
||||
private AfterTransactionAssertion assertAfterTransaction(Person person) {
|
||||
|
||||
AfterTransactionAssertion assertion = new AfterTransactionAssertion<>(new Persistable<Object>() {
|
||||
|
||||
Reference in New Issue
Block a user