Skip to content

Commit bcba123

Browse files
mp911dechristophstrobl
authored andcommittedApr 13, 2017
DATAMONGO-1666 - Consider collection type in bulk DBRef fetching.
We now consider the property's collection type after bulk-fetching DBRefs before returning the actual result value. The issue got only visible if bulk fetching is possible and constructor creation is used. Setting the property value on through an property accessor works fine because the property accessor checks all values for assignability and potentially converts values to their target type. That's different for constructor creation. Original Pull Request: spring-projects#457
1 parent 935db07 commit bcba123

File tree

2 files changed

+52
-18
lines changed

2 files changed

+52
-18
lines changed
 

‎spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import org.bson.conversions.Bson;
3232
import org.slf4j.Logger;
3333
import org.slf4j.LoggerFactory;
34+
3435
import org.springframework.beans.BeansException;
3536
import org.springframework.context.ApplicationContext;
3637
import org.springframework.context.ApplicationContextAware;
@@ -55,7 +56,6 @@
5556
import org.springframework.data.mapping.model.SpELExpressionEvaluator;
5657
import org.springframework.data.mapping.model.SpELExpressionParameterValueProvider;
5758
import org.springframework.data.mongodb.MongoDbFactory;
58-
import org.springframework.data.mongodb.core.convert.MongoConverters.ObjectIdToBigIntegerConverter;
5959
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
6060
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
6161
import org.springframework.data.mongodb.core.mapping.event.AfterConvertEvent;
@@ -241,10 +241,9 @@ private <S extends Object> S read(TypeInformation<S> type, Bson bson, ObjectPath
241241
}
242242
// Retrieve persistent entity info
243243

244-
Document target = bson instanceof BasicDBObject ? new Document((BasicDBObject)bson) : (Document) bson;
244+
Document target = bson instanceof BasicDBObject ? new Document((BasicDBObject) bson) : (Document) bson;
245245

246-
return read((MongoPersistentEntity<S>) mappingContext.getRequiredPersistentEntity(typeToUse), target,
247-
path);
246+
return read((MongoPersistentEntity<S>) mappingContext.getRequiredPersistentEntity(typeToUse), target, path);
248247
}
249248

250249
private ParameterValueProvider<MongoPersistentProperty> getParameterProvider(MongoPersistentEntity<?> entity,
@@ -870,7 +869,7 @@ protected DBRef createDBRef(Object target, MongoPersistentProperty property) {
870869
}
871870

872871
return dbRefResolver.createDbRef(property == null ? null : property.getDBRef(), entity,
873-
idMapper.convertId(id instanceof Optional ? (Optional)id : Optional.ofNullable(id)).orElse(null));
872+
idMapper.convertId(id instanceof Optional ? (Optional) id : Optional.ofNullable(id)).orElse(null));
874873

875874
}).orElseThrow(() -> new MappingException("No id property found on class " + entity.getType()));
876875
}
@@ -913,7 +912,10 @@ private Object readCollectionOrArray(TypeInformation<?> targetType, List sourceV
913912
}
914913

915914
if (!DBRef.class.equals(rawComponentType) && isCollectionOfDbRefWhereBulkFetchIsPossible(sourceValue)) {
916-
return bulkReadAndConvertDBRefs((List<DBRef>) (List) (sourceValue), componentType, path, rawComponentType);
915+
916+
List<Object> objects = bulkReadAndConvertDBRefs((List<DBRef>) sourceValue, componentType, path,
917+
rawComponentType);
918+
return getPotentiallyConvertedSimpleRead(objects, targetType.getType());
917919
}
918920

919921
for (Object dbObjItem : sourceValue) {

‎spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DbRefMappingMongoConverterUnitTests.java

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,19 +29,18 @@
2929
import java.util.LinkedList;
3030
import java.util.List;
3131
import java.util.Map;
32+
import java.util.Set;
3233

33-
import com.mongodb.BasicDBObject;
34-
import org.bson.BsonDocument;
3534
import org.bson.Document;
3635
import org.bson.conversions.Bson;
3736
import org.bson.types.ObjectId;
3837
import org.junit.Before;
3938
import org.junit.Test;
4039
import org.junit.runner.RunWith;
41-
import org.mockito.Matchers;
4240
import org.mockito.Mock;
4341
import org.mockito.Mockito;
4442
import org.mockito.junit.MockitoJUnitRunner;
43+
4544
import org.springframework.data.annotation.AccessType;
4645
import org.springframework.data.annotation.AccessType.Type;
4746
import org.springframework.data.annotation.Id;
@@ -65,7 +64,7 @@
6564

6665
/**
6766
* Unit tests for {@link DbRefMappingMongoConverter}.
68-
*
67+
*
6968
* @author Oliver Gierke
7069
* @author Thomas Darimont
7170
* @author Christoph Strobl
@@ -485,7 +484,8 @@ public void shouldEagerlyResolveIdPropertyWithFieldAccess() {
485484
ClassWithLazyDbRefs result = converter.read(ClassWithLazyDbRefs.class, object);
486485

487486
PersistentPropertyAccessor accessor = propertyEntity.getPropertyAccessor(result.dbRefToConcreteType);
488-
MongoPersistentProperty idProperty = mappingContext.getRequiredPersistentEntity(LazyDbRefTarget.class).getIdProperty().get();
487+
MongoPersistentProperty idProperty = mappingContext.getRequiredPersistentEntity(LazyDbRefTarget.class)
488+
.getIdProperty().get();
489489

490490
assertThat(accessor.getProperty(idProperty), is(notNullValue()));
491491
assertProxyIsResolved(result.dbRefToConcreteType, false);
@@ -512,7 +512,8 @@ public void shouldNotEagerlyResolveIdPropertyWithPropertyAccess() {
512512
@Test // DATAMONGO-1076
513513
public void shouldNotTriggerResolvingOfLazyLoadedProxyWhenFinalizeMethodIsInvoked() throws Exception {
514514

515-
MongoPersistentEntity<?> entity = mappingContext.getRequiredPersistentEntity(WithObjectMethodOverrideLazyDbRefs.class);
515+
MongoPersistentEntity<?> entity = mappingContext
516+
.getRequiredPersistentEntity(WithObjectMethodOverrideLazyDbRefs.class);
516517
MongoPersistentProperty property = entity.getRequiredPersistentProperty("dbRefToPlainObject");
517518

518519
String idValue = new ObjectId().toString();
@@ -534,8 +535,9 @@ public void shouldBulkFetchListOfReferences() {
534535
String value = "val";
535536

536537
MappingMongoConverter converterSpy = spy(converter);
537-
doReturn(Arrays.asList(new Document("_id", id1).append("value", value),
538-
new Document("_id", id2).append("value", value))).when(converterSpy).bulkReadRefs(anyListOf(DBRef.class));
538+
doReturn(
539+
Arrays.asList(new Document("_id", id1).append("value", value), new Document("_id", id2).append("value", value)))
540+
.when(converterSpy).bulkReadRefs(anyListOf(DBRef.class));
539541

540542
Document document = new Document();
541543
ClassWithLazyDbRefs lazyDbRefs = new ClassWithLazyDbRefs();
@@ -553,6 +555,28 @@ public void shouldBulkFetchListOfReferences() {
553555
verify(converterSpy, never()).readRef(Mockito.any(DBRef.class));
554556
}
555557

558+
@Test // DATAMONGO-1666
559+
public void shouldBulkFetchSetOfReferencesForConstructorCreation() {
560+
561+
String id1 = "1";
562+
String id2 = "2";
563+
String value = "val";
564+
565+
MappingMongoConverter converterSpy = spy(converter);
566+
doReturn(
567+
Arrays.asList(new Document("_id", id1).append("value", value), new Document("_id", id2).append("value", value)))
568+
.when(converterSpy).bulkReadRefs(any());
569+
570+
Document document = new Document("dbRefToInterface",
571+
Arrays.asList(new DBRef("lazyDbRefTarget", "1"), new DBRef("lazyDbRefTarget", "2")));
572+
573+
ClassWithDbRefSetConstructor result = converterSpy.read(ClassWithDbRefSetConstructor.class, document);
574+
575+
assertThat(result.dbRefToInterface, is(instanceOf(Set.class)));
576+
577+
verify(converterSpy, never()).readRef(Mockito.any(DBRef.class));
578+
}
579+
556580
@Test // DATAMONGO-1194
557581
public void shouldFallbackToOneByOneFetchingWhenElementsInListOfReferencesPointToDifferentCollections() {
558582

@@ -561,9 +585,8 @@ public void shouldFallbackToOneByOneFetchingWhenElementsInListOfReferencesPointT
561585
String value = "val";
562586

563587
MappingMongoConverter converterSpy = spy(converter);
564-
doReturn(new Document("_id", id1).append("value", value))
565-
.doReturn(new Document("_id", id2).append("value", value)).when(converterSpy)
566-
.readRef(Mockito.any(DBRef.class));
588+
doReturn(new Document("_id", id1).append("value", value)).doReturn(new Document("_id", id2).append("value", value))
589+
.when(converterSpy).readRef(Mockito.any(DBRef.class));
567590

568591
Document document = new Document();
569592
ClassWithLazyDbRefs lazyDbRefs = new ClassWithLazyDbRefs();
@@ -678,6 +701,15 @@ static class ClassWithLazyDbRefs {
678701
lazy = true) LazyDbRefTargetWithPeristenceConstructorWithoutDefaultConstructor dbRefToConcreteTypeWithPersistenceConstructorWithoutDefaultConstructor;
679702
}
680703

704+
static class ClassWithDbRefSetConstructor {
705+
706+
final @org.springframework.data.mongodb.core.mapping.DBRef Set<LazyDbRefTarget> dbRefToInterface;
707+
708+
public ClassWithDbRefSetConstructor(Set<LazyDbRefTarget> dbRefToInterface) {
709+
this.dbRefToInterface = dbRefToInterface;
710+
}
711+
}
712+
681713
static class SerializableClassWithLazyDbRefs implements Serializable {
682714

683715
private static final long serialVersionUID = 1L;
@@ -785,7 +817,7 @@ public ToStringObjectMethodOverrideLazyDbRefTarget(String id, String value) {
785817
super(id, value);
786818
}
787819

788-
/*
820+
/*
789821
* (non-Javadoc)
790822
* @see java.lang.Object#toString()
791823
*/

0 commit comments

Comments
 (0)
Please sign in to comment.