Fix @DocumentReference resolution for properties used in constructor.
This commit fixes an issue that prevented referenced entities from being used as constructor arguments. Closes: #3806 Original pull request: #3810.
This commit is contained in:
committed by
Mark Paluch
parent
270456ed81
commit
f128e6df15
@@ -530,7 +530,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
|
||||
if (conversionService.canConvert(DocumentPointer.class, property.getActualType())) {
|
||||
|
||||
if(value == null) {
|
||||
if (value == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -541,7 +541,9 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
} else {
|
||||
|
||||
accessor.setProperty(property,
|
||||
dbRefResolver.resolveReference(property, new DocumentReferenceSource(documentAccessor.getDocument(), documentAccessor.get(property)), referenceLookupDelegate, context::convert));
|
||||
dbRefResolver.resolveReference(property,
|
||||
new DocumentReferenceSource(documentAccessor.getDocument(), documentAccessor.get(property)),
|
||||
referenceLookupDelegate, context::convert));
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -875,10 +877,12 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
if (property.isAssociation()) {
|
||||
|
||||
List<Object> targetCollection = collection.stream().map(it -> {
|
||||
return documentPointerFactory.computePointer(mappingContext, property, it, property.getActualType()).getPointer();
|
||||
return documentPointerFactory.computePointer(mappingContext, property, it, property.getActualType())
|
||||
.getPointer();
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
return writeCollectionInternal(targetCollection, ClassTypeInformation.from(DocumentPointer.class), new ArrayList<>());
|
||||
return writeCollectionInternal(targetCollection, ClassTypeInformation.from(DocumentPointer.class),
|
||||
new ArrayList<>());
|
||||
}
|
||||
|
||||
if (property.hasExplicitWriteTarget()) {
|
||||
@@ -931,7 +935,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
if (property.isDbReference()) {
|
||||
document.put(simpleKey, value != null ? createDBRef(value, property) : null);
|
||||
} else {
|
||||
document.put(simpleKey, documentPointerFactory.computePointer(mappingContext, property, value, property.getActualType()).getPointer());
|
||||
document.put(simpleKey, documentPointerFactory
|
||||
.computePointer(mappingContext, property, value, property.getActualType()).getPointer());
|
||||
}
|
||||
|
||||
} else {
|
||||
@@ -1814,6 +1819,11 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
return (T) dbRefResolver.resolveDbRef(property, dbref, callback, dbRefProxyHandler);
|
||||
}
|
||||
|
||||
if (property.isDocumentReference()) {
|
||||
return (T) dbRefResolver.resolveReference(property, accessor.get(property), referenceLookupDelegate,
|
||||
context::convert);
|
||||
}
|
||||
|
||||
return super.getPropertyValue(property);
|
||||
}
|
||||
}
|
||||
@@ -2036,7 +2046,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
|
||||
if (typeHint.isMap()) {
|
||||
|
||||
if(ClassUtils.isAssignable(Document.class, typeHint.getType())) {
|
||||
if (ClassUtils.isAssignable(Document.class, typeHint.getType())) {
|
||||
return (S) documentConverter.convert(this, BsonUtils.asBson(source), typeHint);
|
||||
}
|
||||
|
||||
@@ -2044,7 +2054,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
return (S) mapConverter.convert(this, BsonUtils.asBson(source), typeHint);
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException(String.format("Expected map like structure but found %s", source.getClass()));
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Expected map like structure but found %s", source.getClass()));
|
||||
}
|
||||
|
||||
if (source instanceof DBRef) {
|
||||
|
||||
@@ -733,6 +733,52 @@ public class MongoTemplateDocumentReferenceTests {
|
||||
assertThat(result.simplePreinitializedValueRef).isEmpty();
|
||||
}
|
||||
|
||||
@Test // GH-3806
|
||||
void resolveReferenceWhenUsedAsCtorArgument() {
|
||||
|
||||
Publisher publisher = new Publisher();
|
||||
publisher.id = "p-111";
|
||||
publisher.name = "ppp";
|
||||
|
||||
template.save(publisher);
|
||||
|
||||
WithRequiredArgsCtor source = new WithRequiredArgsCtor("id-1", publisher);
|
||||
|
||||
template.save(source);
|
||||
|
||||
WithRequiredArgsCtor target = template.findOne(query(where("id").is(source.id)), WithRequiredArgsCtor.class);
|
||||
assertThat(target.publisher).isNotNull();
|
||||
}
|
||||
|
||||
@Test // GH-3806
|
||||
void resolveLazyReferenceWhenUsedAsCtorArgument() {
|
||||
|
||||
Publisher publisher = new Publisher();
|
||||
publisher.id = "p-111";
|
||||
publisher.name = "ppp";
|
||||
|
||||
template.save(publisher);
|
||||
|
||||
WithLazyRequiredArgsCtor source = new WithLazyRequiredArgsCtor("id-1", publisher);
|
||||
|
||||
template.save(source);
|
||||
|
||||
WithLazyRequiredArgsCtor target = template.findOne(query(where("id").is(source.id)), WithLazyRequiredArgsCtor.class);
|
||||
|
||||
// proxy not yet resolved
|
||||
LazyLoadingTestUtils.assertProxy(target.publisher, (proxy) -> {
|
||||
|
||||
assertThat(proxy.isResolved()).isFalse();
|
||||
assertThat(proxy.currentValue()).isNull();
|
||||
});
|
||||
|
||||
// resolve the proxy by invoking a method on it
|
||||
assertThat(target.getPublisher().getName()).isEqualTo("ppp");
|
||||
LazyLoadingTestUtils.assertProxy(target.publisher, (proxy) -> {
|
||||
assertThat(proxy.isResolved()).isTrue();
|
||||
});
|
||||
}
|
||||
|
||||
@Test // GH-3602
|
||||
void queryForReference() {
|
||||
|
||||
@@ -1371,6 +1417,30 @@ public class MongoTemplateDocumentReferenceTests {
|
||||
String id;
|
||||
String acronym;
|
||||
String name;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getAcronym() {
|
||||
return acronym;
|
||||
}
|
||||
|
||||
public void setAcronym(String acronym) {
|
||||
this.acronym = acronym;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
@Data
|
||||
@@ -1401,4 +1471,40 @@ public class MongoTemplateDocumentReferenceTests {
|
||||
@DocumentReference(lookup="{'publisherId':?#{#self._id} }")
|
||||
List<OneToManyStyleBook> books;
|
||||
}
|
||||
|
||||
static class WithRequiredArgsCtor {
|
||||
|
||||
final String id;
|
||||
|
||||
@DocumentReference
|
||||
final Publisher publisher;
|
||||
|
||||
public WithRequiredArgsCtor(String id, Publisher publisher) {
|
||||
|
||||
this.id = id;
|
||||
this.publisher = publisher;
|
||||
}
|
||||
}
|
||||
|
||||
static class WithLazyRequiredArgsCtor {
|
||||
|
||||
final String id;
|
||||
|
||||
@DocumentReference(lazy = true)
|
||||
final Publisher publisher;
|
||||
|
||||
public WithLazyRequiredArgsCtor(String id, Publisher publisher) {
|
||||
|
||||
this.id = id;
|
||||
this.publisher = publisher;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public Publisher getPublisher() {
|
||||
return publisher;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user