Browse Source

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.
pull/3821/head
Christoph Strobl 4 years ago committed by Mark Paluch
parent
commit
f128e6df15
No known key found for this signature in database
GPG Key ID: 4406B84C1661DCD1
  1. 21
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java
  2. 106
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDocumentReferenceTests.java

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

@ -541,7 +541,9 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App @@ -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 @@ -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 @@ -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 @@ -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);
}
}
@ -2044,7 +2054,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App @@ -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) {

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

@ -733,6 +733,52 @@ public class MongoTemplateDocumentReferenceTests { @@ -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 { @@ -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 { @@ -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;
}
}
}

Loading…
Cancel
Save