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.
This commit is contained in:
committed by
Mark Paluch
parent
f7cf23510c
commit
5f33987741
@@ -15,8 +15,10 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.convert;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.bson.Document;
|
||||
@@ -34,6 +36,7 @@ import org.springframework.data.mongodb.core.query.Update.Modifiers;
|
||||
import org.springframework.data.util.ClassTypeInformation;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* A subclass of {@link QueryMapper} that retains type information on the mongo types.
|
||||
@@ -221,8 +224,18 @@ public class UpdateMapper extends QueryMapper {
|
||||
: getMappedSort(sortObject, field.getPropertyEntity());
|
||||
}
|
||||
|
||||
TypeInformation<?> typeHint = field == null ? ClassTypeInformation.OBJECT : field.getTypeHint();
|
||||
if (isAssociationConversionNecessary(field, value)) {
|
||||
if (ObjectUtils.isArray(value) || value instanceof Collection) {
|
||||
List<Object> targetPointers = new ArrayList<>();
|
||||
for (Object val : converter.getConversionService().convert(value, List.class)) {
|
||||
targetPointers.add(getMappedValue(field, val));
|
||||
}
|
||||
return targetPointers;
|
||||
}
|
||||
return super.getMappedValue(field, value);
|
||||
}
|
||||
|
||||
TypeInformation<?> typeHint = field == null ? ClassTypeInformation.OBJECT : field.getTypeHint();
|
||||
return converter.convertToMongoType(value, typeHint);
|
||||
}
|
||||
|
||||
|
||||
@@ -903,6 +903,29 @@ public class MongoTemplateDocumentReferenceTests {
|
||||
assertThat(target).containsEntry("toB", "b");
|
||||
}
|
||||
|
||||
@Test // GH-4041
|
||||
void updateReferenceWithPushToCollection() {
|
||||
|
||||
WithListOfRefs a = new WithListOfRefs();
|
||||
a.id = "a";
|
||||
template.save(a);
|
||||
|
||||
WithListOfRefs b = new WithListOfRefs();
|
||||
b.id = "b";
|
||||
template.save(b);
|
||||
|
||||
template.update(WithListOfRefs.class).matching(where("id").is(a.id))
|
||||
.apply(new Update().push("refs").each(new Object[] { b })).first();
|
||||
|
||||
String collection = template.getCollectionName(WithListOfRefs.class);
|
||||
|
||||
Document target = template.execute(db -> {
|
||||
return db.getCollection(collection).find(Filters.eq("_id", "a")).first();
|
||||
});
|
||||
|
||||
assertThat(target).containsEntry("refs", Collections.singletonList("b"));
|
||||
}
|
||||
|
||||
@Test // GH-3782
|
||||
void updateReferenceHavingCustomizedIdTargetType() {
|
||||
|
||||
@@ -1584,4 +1607,11 @@ public class MongoTemplateDocumentReferenceTests {
|
||||
return publisher;
|
||||
}
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class WithListOfRefs {
|
||||
@Id private String id;
|
||||
|
||||
@DocumentReference private List<WithListOfRefs> refs;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user