Skip to content

Commit f31a072

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

File tree

3 files changed

+89
-2
lines changed

3 files changed

+89
-2
lines changed

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

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

597597
ConversionContext propertyContext = context.forProperty(prop);
598-
MongoDbPropertyValueProvider valueProviderToUse = valueProvider.withContext(propertyContext);
599598

600599
if (prop.isAssociation()) {
601600

@@ -623,7 +622,7 @@ private void readProperties(ConversionContext context, MongoPersistentEntity<?>
623622
continue;
624623
}
625624

626-
accessor.setProperty(prop, valueProviderToUse.getPropertyValue(prop));
625+
accessor.setProperty(prop, valueProvider.getPropertyValue(prop));
627626
}
628627
}
629628

@@ -2436,6 +2435,8 @@ class ProjectingConversionContext extends DefaultConversionContext {
24362435
this.returnedTypeDescriptor = projection;
24372436
}
24382437

2438+
2439+
24392440
@Override
24402441
public ConversionContext forProperty(String name) {
24412442

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

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

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

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

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

2854+
@Test // GH-4609
2855+
void projectShouldReadNestedInterfaceProjection() {
2856+
2857+
org.bson.Document source = new org.bson.Document("foo", "spring").append("address",
2858+
new org.bson.Document("s", "data").append("city", "mongodb"));
2859+
2860+
EntityProjectionIntrospector introspector = EntityProjectionIntrospector.create(converter.getProjectionFactory(),
2861+
EntityProjectionIntrospector.ProjectionPredicate.typeHierarchy()
2862+
.and((target, underlyingType) -> !converter.conversions.isSimpleType(target)),
2863+
mappingContext);
2864+
2865+
EntityProjection<WithNestedInterfaceProjection, Person> projection = introspector.introspect(WithNestedInterfaceProjection.class,
2866+
Person.class);
2867+
WithNestedInterfaceProjection person = converter.project(projection, source);
2868+
2869+
assertThat(person.getFirstname()).isEqualTo("spring");
2870+
assertThat(person.getAddress().getStreet()).isEqualTo("data");
2871+
}
2872+
2873+
@Test // GH-4609
2874+
void projectShouldReadNestedDtoProjection() {
2875+
2876+
org.bson.Document source = new org.bson.Document("foo", "spring").append("address",
2877+
new org.bson.Document("s", "data").append("city", "mongodb"));
2878+
2879+
EntityProjectionIntrospector introspector = EntityProjectionIntrospector.create(converter.getProjectionFactory(),
2880+
EntityProjectionIntrospector.ProjectionPredicate.typeHierarchy()
2881+
.and((target, underlyingType) -> !converter.conversions.isSimpleType(target)),
2882+
mappingContext);
2883+
2884+
EntityProjection<WithNestedDtoProjection, Person> projection = introspector.introspect(WithNestedDtoProjection.class,
2885+
Person.class);
2886+
WithNestedDtoProjection person = converter.project(projection, source);
2887+
2888+
assertThat(person.getFirstname()).isEqualTo("spring");
2889+
assertThat(person.getAddress().getStreet()).isEqualTo("data");
2890+
}
2891+
28542892
@Test // GH-2860
28552893
void projectShouldReadProjectionWithNestedEntity() {
28562894

@@ -3206,6 +3244,7 @@ static class Person implements Contact {
32063244
String lastname;
32073245

32083246
Set<Address> addresses;
3247+
Address address;
32093248

32103249
Person() {
32113250

@@ -3248,6 +3287,16 @@ interface WithNestedProjection {
32483287
Set<AddressProjection> getAddresses();
32493288
}
32503289

3290+
interface WithNestedInterfaceProjection {
3291+
String getFirstname();
3292+
AddressProjection getAddress();
3293+
}
3294+
3295+
interface WithNestedDtoProjection {
3296+
String getFirstname();
3297+
AddressDto getAddress();
3298+
}
3299+
32513300
interface ProjectionWithNestedEntity {
32523301

32533302
Set<Address> getAddresses();
@@ -3258,6 +3307,19 @@ interface AddressProjection {
32583307
String getStreet();
32593308
}
32603309

3310+
class AddressDto {
3311+
3312+
String street;
3313+
3314+
public String getStreet() {
3315+
return street;
3316+
}
3317+
3318+
public void setStreet(String street) {
3319+
this.street = street;
3320+
}
3321+
}
3322+
32613323
static class PersonDto {
32623324

32633325
LocalDate birthDate;

0 commit comments

Comments
 (0)