Skip to content

Commit 0265581

Browse files
christophstroblmp911de
authored andcommitted
Avoid duplicate context nesting to properly convert nested projections.
Closes: #4609 Original pull request: #4616
1 parent 04adac4 commit 0265581

File tree

3 files changed

+89
-2
lines changed

3 files changed

+89
-2
lines changed

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

+3-2
Original file line numberDiff line numberDiff line change
@@ -583,7 +583,6 @@ private void readProperties(ConversionContext context, MongoPersistentEntity<?>
583583
}
584584

585585
ConversionContext propertyContext = context.forProperty(prop);
586-
MongoDbPropertyValueProvider valueProviderToUse = valueProvider.withContext(propertyContext);
587586

588587
if (prop.isAssociation()) {
589588

@@ -611,7 +610,7 @@ private void readProperties(ConversionContext context, MongoPersistentEntity<?>
611610
continue;
612611
}
613612

614-
accessor.setProperty(prop, valueProviderToUse.getPropertyValue(prop));
613+
accessor.setProperty(prop, valueProvider.getPropertyValue(prop));
615614
}
616615
}
617616

@@ -2427,6 +2426,8 @@ class ProjectingConversionContext extends DefaultConversionContext {
24272426
this.returnedTypeDescriptor = projection;
24282427
}
24292428

2429+
2430+
24302431
@Override
24312432
public ConversionContext forProperty(String name) {
24322433

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

+24
Original file line numberDiff line numberDiff line change
@@ -2552,6 +2552,30 @@ public void findAndReplaceShouldProjectReturnedObjectCorrectly() {
25522552
assertThat(projection.getName()).isEqualTo("Walter");
25532553
}
25542554

2555+
@Test // GH-4609
2556+
public void shouldReadNestedProjection() {
2557+
2558+
MyPerson walter = new MyPerson("Walter");
2559+
walter.address = new Address("spring", "data");
2560+
template.save(walter);
2561+
2562+
PersonPWA result = template.query(MyPerson.class)
2563+
.as(PersonPWA.class)
2564+
.matching(where("id").is(walter.id))
2565+
.firstValue();
2566+
2567+
assertThat(result.getAddress().getCity()).isEqualTo("data");
2568+
}
2569+
2570+
interface PersonPWA {
2571+
String getName();
2572+
AdressProjection getAddress();
2573+
}
2574+
2575+
interface AdressProjection {
2576+
String getCity();
2577+
}
2578+
25552579
@Test // GH-4300
25562580
public void findAndReplaceShouldAllowNativeDomainTypesAndReturnAProjection() {
25572581

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java

+62
Original file line numberDiff line numberDiff line change
@@ -2709,6 +2709,44 @@ void projectShouldReadNestedProjection() {
27092709
assertThat(person.getAddresses()).extracting(AddressProjection::getStreet).hasSize(1).containsOnly("hwy");
27102710
}
27112711

2712+
@Test // GH-4609
2713+
void projectShouldReadNestedInterfaceProjection() {
2714+
2715+
org.bson.Document source = new org.bson.Document("foo", "spring").append("address",
2716+
new org.bson.Document("s", "data").append("city", "mongodb"));
2717+
2718+
EntityProjectionIntrospector introspector = EntityProjectionIntrospector.create(converter.getProjectionFactory(),
2719+
EntityProjectionIntrospector.ProjectionPredicate.typeHierarchy()
2720+
.and((target, underlyingType) -> !converter.conversions.isSimpleType(target)),
2721+
mappingContext);
2722+
2723+
EntityProjection<WithNestedInterfaceProjection, Person> projection = introspector.introspect(WithNestedInterfaceProjection.class,
2724+
Person.class);
2725+
WithNestedInterfaceProjection person = converter.project(projection, source);
2726+
2727+
assertThat(person.getFirstname()).isEqualTo("spring");
2728+
assertThat(person.getAddress().getStreet()).isEqualTo("data");
2729+
}
2730+
2731+
@Test // GH-4609
2732+
void projectShouldReadNestedDtoProjection() {
2733+
2734+
org.bson.Document source = new org.bson.Document("foo", "spring").append("address",
2735+
new org.bson.Document("s", "data").append("city", "mongodb"));
2736+
2737+
EntityProjectionIntrospector introspector = EntityProjectionIntrospector.create(converter.getProjectionFactory(),
2738+
EntityProjectionIntrospector.ProjectionPredicate.typeHierarchy()
2739+
.and((target, underlyingType) -> !converter.conversions.isSimpleType(target)),
2740+
mappingContext);
2741+
2742+
EntityProjection<WithNestedDtoProjection, Person> projection = introspector.introspect(WithNestedDtoProjection.class,
2743+
Person.class);
2744+
WithNestedDtoProjection person = converter.project(projection, source);
2745+
2746+
assertThat(person.getFirstname()).isEqualTo("spring");
2747+
assertThat(person.getAddress().getStreet()).isEqualTo("data");
2748+
}
2749+
27122750
@Test // GH-2860
27132751
void projectShouldReadProjectionWithNestedEntity() {
27142752

@@ -2958,6 +2996,7 @@ static class Person implements Contact {
29582996
String lastname;
29592997

29602998
Set<Address> addresses;
2999+
Address address;
29613000

29623001
Person() {
29633002

@@ -2981,6 +3020,16 @@ interface WithNestedProjection {
29813020
Set<AddressProjection> getAddresses();
29823021
}
29833022

3023+
interface WithNestedInterfaceProjection {
3024+
String getFirstname();
3025+
AddressProjection getAddress();
3026+
}
3027+
3028+
interface WithNestedDtoProjection {
3029+
String getFirstname();
3030+
AddressDto getAddress();
3031+
}
3032+
29843033
interface ProjectionWithNestedEntity {
29853034

29863035
Set<Address> getAddresses();
@@ -2991,6 +3040,19 @@ interface AddressProjection {
29913040
String getStreet();
29923041
}
29933042

3043+
class AddressDto {
3044+
3045+
String street;
3046+
3047+
public String getStreet() {
3048+
return street;
3049+
}
3050+
3051+
public void setStreet(String street) {
3052+
this.street = street;
3053+
}
3054+
}
3055+
29943056
static class PersonDto {
29953057

29963058
LocalDate birthDate;

0 commit comments

Comments
 (0)