diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java index 26d7c0001..14e956153 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java @@ -33,7 +33,6 @@ import org.bson.codecs.Codec; import org.bson.conversions.Bson; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; @@ -260,7 +259,15 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, this.mongoDbFactory = dbFactory; this.exceptionTranslator = that.exceptionTranslator; this.sessionSynchronization = that.sessionSynchronization; - this.mongoConverter = that.mongoConverter; + + // we need to (re)create the MappingMongoConverter as we need to have it use a DbRefResolver that operates within + // the sames session. Otherwise loading referenced objects would happen outside of it. + if (that.mongoConverter instanceof MappingMongoConverter) { + this.mongoConverter = ((MappingMongoConverter) that.mongoConverter).with(dbFactory); + } else { + this.mongoConverter = that.mongoConverter; + } + this.queryMapper = that.queryMapper; this.updateMapper = that.updateMapper; this.schemaMapper = that.schemaMapper; diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java index bc3784848..13f4e1cd5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java @@ -28,7 +28,9 @@ import org.springframework.context.ApplicationContextAware; import org.springframework.core.CollectionFactory; import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.support.DefaultConversionService; +import org.springframework.data.convert.CustomConversions; import org.springframework.data.convert.EntityInstantiator; +import org.springframework.data.convert.EntityInstantiators; import org.springframework.data.convert.TypeMapper; import org.springframework.data.mapping.Association; import org.springframework.data.mapping.MappingException; @@ -1596,6 +1598,26 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App return dbRefResolver.bulkFetch(references); } + + /** + * Create a new {@link MappingMongoConverter} using the given {@link MongoDbFactory} when loading {@link DBRef}. + * + * @return new instance of {@link MappingMongoConverter}. Never {@literal null}. + * @since 2.1.6 + */ + public MappingMongoConverter with(MongoDbFactory dbFactory) { + + MappingMongoConverter target = new MappingMongoConverter(new DefaultDbRefResolver(dbFactory), mappingContext); + target.applicationContext = applicationContext; + target.conversions = conversions; + target.spELContext = spELContext; + target.setInstantiators(instantiators); + target.typeMapper = typeMapper; + target.afterPropertiesSet(); + + return target; + } + /** * Returns whether the given {@link Iterable} contains {@link DBRef} instances all pointing to the same collection. * diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ClientSessionTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ClientSessionTests.java index 2a8280bbc..39e595c50 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ClientSessionTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ClientSessionTests.java @@ -29,15 +29,15 @@ import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TestRule; - import org.springframework.data.annotation.Id; -import org.springframework.data.mongodb.core.convert.MongoConverter; +import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.test.util.MongoTestUtils; import org.springframework.data.mongodb.test.util.MongoVersion; import org.springframework.data.mongodb.test.util.MongoVersionRule; import org.springframework.data.mongodb.test.util.ReplicaSet; import org.springframework.data.util.Version; +import org.springframework.test.util.ReflectionTestUtils; import com.mongodb.ClientSessionOptions; import com.mongodb.MongoClient; @@ -92,15 +92,19 @@ public class ClientSessionTests { } @Test // DATAMONGO-2241 - public void shouldReuseConfiguredConverter() { + public void shouldReuseConfiguredInfrastructure() { ClientSession session = client.startSession(ClientSessionOptions.builder().causallyConsistent(true).build()); - MongoConverter converter = template.getConverter(); - MongoConverter sessionTemplateConverter = template.withSession(() -> session) - .execute(MongoOperations::getConverter); + MappingMongoConverter source = MappingMongoConverter.class.cast(template.getConverter()); + MappingMongoConverter sessionTemplateConverter = MappingMongoConverter.class + .cast(template.withSession(() -> session).execute(MongoOperations::getConverter)); - assertThat(sessionTemplateConverter).isSameAs(converter); + assertThat(sessionTemplateConverter.getMappingContext()).isSameAs(source.getMappingContext()); + assertThat(ReflectionTestUtils.getField(sessionTemplateConverter, "conversions")) + .isSameAs(ReflectionTestUtils.getField(source, "conversions")); + assertThat(ReflectionTestUtils.getField(sessionTemplateConverter, "instantiators")) + .isSameAs(ReflectionTestUtils.getField(source, "instantiators")); } @Test // DATAMONGO-1920