Skip to content

Commit e88c9cf

Browse files
christophstroblmp911de
authored andcommitted
Fix issue with reference conversion in updates.
We now make sure to convert references in update operations targeting collection like fields when using eg. the push modifier. Closes #4041 Original pull request: #4045.
1 parent fadca10 commit e88c9cf

File tree

2 files changed

+45
-2
lines changed

2 files changed

+45
-2
lines changed

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

+15-2
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@
1515
*/
1616
package org.springframework.data.mongodb.core.convert;
1717

18+
import java.util.ArrayList;
1819
import java.util.Collection;
1920
import java.util.LinkedHashMap;
21+
import java.util.List;
2022
import java.util.Map.Entry;
2123

2224
import org.bson.Document;
@@ -33,6 +35,7 @@
3335
import org.springframework.data.mongodb.core.query.Update.Modifiers;
3436
import org.springframework.data.util.TypeInformation;
3537
import org.springframework.lang.Nullable;
38+
import org.springframework.util.ObjectUtils;
3639

3740
/**
3841
* A subclass of {@link QueryMapper} that retains type information on the mongo types.
@@ -128,7 +131,7 @@ public static boolean isUpdateObject(@Nullable Document updateObj) {
128131
@Override
129132
protected Object delegateConvertToMongoType(Object source, @Nullable MongoPersistentEntity<?> entity) {
130133

131-
if(entity != null && entity.isUnwrapped()) {
134+
if (entity != null && entity.isUnwrapped()) {
132135
return converter.convertToMongoType(source, entity);
133136
}
134137

@@ -208,8 +211,18 @@ private Object getMappedModifier(@Nullable Field field, Modifier modifier) {
208211
: getMappedSort(sortObject, field.getPropertyEntity());
209212
}
210213

211-
TypeInformation<?> typeHint = field == null ? TypeInformation.OBJECT : field.getTypeHint();
214+
if (isAssociationConversionNecessary(field, value)) {
215+
if (ObjectUtils.isArray(value) || value instanceof Collection) {
216+
List<Object> targetPointers = new ArrayList<>();
217+
for (Object val : converter.getConversionService().convert(value, List.class)) {
218+
targetPointers.add(getMappedValue(field, val));
219+
}
220+
return targetPointers;
221+
}
222+
return super.getMappedValue(field, value);
223+
}
212224

225+
TypeInformation<?> typeHint = field == null ? TypeInformation.OBJECT : field.getTypeHint();
213226
return converter.convertToMongoType(value, typeHint);
214227
}
215228

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDocumentReferenceTests.java

+30
Original file line numberDiff line numberDiff line change
@@ -903,6 +903,29 @@ void updateReferenceWithValue() {
903903
assertThat(target).containsEntry("toB", "b");
904904
}
905905

906+
@Test // GH-4041
907+
void updateReferenceWithPushToCollection() {
908+
909+
WithListOfRefs a = new WithListOfRefs();
910+
a.id = "a";
911+
template.save(a);
912+
913+
WithListOfRefs b = new WithListOfRefs();
914+
b.id = "b";
915+
template.save(b);
916+
917+
template.update(WithListOfRefs.class).matching(where("id").is(a.id))
918+
.apply(new Update().push("refs").each(new Object[] { b })).first();
919+
920+
String collection = template.getCollectionName(WithListOfRefs.class);
921+
922+
Document target = template.execute(db -> {
923+
return db.getCollection(collection).find(Filters.eq("_id", "a")).first();
924+
});
925+
926+
assertThat(target).containsEntry("refs", Collections.singletonList("b"));
927+
}
928+
906929
@Test // GH-3782
907930
void updateReferenceHavingCustomizedIdTargetType() {
908931

@@ -1584,4 +1607,11 @@ public Publisher getPublisher() {
15841607
return publisher;
15851608
}
15861609
}
1610+
1611+
@Data
1612+
public static class WithListOfRefs {
1613+
@Id private String id;
1614+
1615+
@DocumentReference private List<WithListOfRefs> refs;
1616+
}
15871617
}

0 commit comments

Comments
 (0)