Avoid duplicate context nesting to properly convert nested projections.

Closes: #4609
Original pull request: #4616
This commit is contained in:
Christoph Strobl
2024-01-15 08:32:41 +01:00
committed by Mark Paluch
parent 48777564c9
commit f31a072f07
3 changed files with 89 additions and 2 deletions

View File

@@ -595,7 +595,6 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
}
ConversionContext propertyContext = context.forProperty(prop);
MongoDbPropertyValueProvider valueProviderToUse = valueProvider.withContext(propertyContext);
if (prop.isAssociation()) {
@@ -623,7 +622,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
continue;
}
accessor.setProperty(prop, valueProviderToUse.getPropertyValue(prop));
accessor.setProperty(prop, valueProvider.getPropertyValue(prop));
}
}
@@ -2436,6 +2435,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
this.returnedTypeDescriptor = projection;
}
@Override
public ConversionContext forProperty(String name) {

View File

@@ -2554,6 +2554,30 @@ public class MongoTemplateTests {
assertThat(projection.getName()).isEqualTo("Walter");
}
@Test // GH-4609
public void shouldReadNestedProjection() {
MyPerson walter = new MyPerson("Walter");
walter.address = new Address("spring", "data");
template.save(walter);
PersonPWA result = template.query(MyPerson.class)
.as(PersonPWA.class)
.matching(where("id").is(walter.id))
.firstValue();
assertThat(result.getAddress().getCity()).isEqualTo("data");
}
interface PersonPWA {
String getName();
AdressProjection getAddress();
}
interface AdressProjection {
String getCity();
}
@Test // GH-4300
public void findAndReplaceShouldAllowNativeDomainTypesAndReturnAProjection() {

View File

@@ -2851,6 +2851,44 @@ class MappingMongoConverterUnitTests {
assertThat(person.getAddresses()).extracting(AddressProjection::getStreet).hasSize(1).containsOnly("hwy");
}
@Test // GH-4609
void projectShouldReadNestedInterfaceProjection() {
org.bson.Document source = new org.bson.Document("foo", "spring").append("address",
new org.bson.Document("s", "data").append("city", "mongodb"));
EntityProjectionIntrospector introspector = EntityProjectionIntrospector.create(converter.getProjectionFactory(),
EntityProjectionIntrospector.ProjectionPredicate.typeHierarchy()
.and((target, underlyingType) -> !converter.conversions.isSimpleType(target)),
mappingContext);
EntityProjection<WithNestedInterfaceProjection, Person> projection = introspector.introspect(WithNestedInterfaceProjection.class,
Person.class);
WithNestedInterfaceProjection person = converter.project(projection, source);
assertThat(person.getFirstname()).isEqualTo("spring");
assertThat(person.getAddress().getStreet()).isEqualTo("data");
}
@Test // GH-4609
void projectShouldReadNestedDtoProjection() {
org.bson.Document source = new org.bson.Document("foo", "spring").append("address",
new org.bson.Document("s", "data").append("city", "mongodb"));
EntityProjectionIntrospector introspector = EntityProjectionIntrospector.create(converter.getProjectionFactory(),
EntityProjectionIntrospector.ProjectionPredicate.typeHierarchy()
.and((target, underlyingType) -> !converter.conversions.isSimpleType(target)),
mappingContext);
EntityProjection<WithNestedDtoProjection, Person> projection = introspector.introspect(WithNestedDtoProjection.class,
Person.class);
WithNestedDtoProjection person = converter.project(projection, source);
assertThat(person.getFirstname()).isEqualTo("spring");
assertThat(person.getAddress().getStreet()).isEqualTo("data");
}
@Test // GH-2860
void projectShouldReadProjectionWithNestedEntity() {
@@ -3206,6 +3244,7 @@ class MappingMongoConverterUnitTests {
String lastname;
Set<Address> addresses;
Address address;
Person() {
@@ -3248,6 +3287,16 @@ class MappingMongoConverterUnitTests {
Set<AddressProjection> getAddresses();
}
interface WithNestedInterfaceProjection {
String getFirstname();
AddressProjection getAddress();
}
interface WithNestedDtoProjection {
String getFirstname();
AddressDto getAddress();
}
interface ProjectionWithNestedEntity {
Set<Address> getAddresses();
@@ -3258,6 +3307,19 @@ class MappingMongoConverterUnitTests {
String getStreet();
}
class AddressDto {
String street;
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
}
static class PersonDto {
LocalDate birthDate;