Browse Source

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.
3.3.x
Christoph Strobl 4 years ago committed by Mark Paluch
parent
commit
34a2d09303
No known key found for this signature in database
GPG Key ID: 4406B84C1661DCD1
  1. 15
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/UpdateMapper.java
  2. 30
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDocumentReferenceTests.java

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

@ -15,8 +15,10 @@
*/ */
package org.springframework.data.mongodb.core.convert; package org.springframework.data.mongodb.core.convert;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map.Entry; import java.util.Map.Entry;
import org.bson.Document; 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.ClassTypeInformation;
import org.springframework.data.util.TypeInformation; import org.springframework.data.util.TypeInformation;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
import org.springframework.util.ObjectUtils;
/** /**
* A subclass of {@link QueryMapper} that retains type information on the mongo types. * 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()); : 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); return converter.convertToMongoType(value, typeHint);
} }

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

@ -903,6 +903,29 @@ public class MongoTemplateDocumentReferenceTests {
assertThat(target).containsEntry("toB", "b"); 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 @Test // GH-3782
void updateReferenceHavingCustomizedIdTargetType() { void updateReferenceHavingCustomizedIdTargetType() {
@ -1584,4 +1607,11 @@ public class MongoTemplateDocumentReferenceTests {
return publisher; return publisher;
} }
} }
@Data
public static class WithListOfRefs {
@Id private String id;
@DocumentReference private List<WithListOfRefs> refs;
}
} }

Loading…
Cancel
Save