Skip to content

Commit 0474f65

Browse files
christophstroblmp911de
authored andcommitted
Fix id value conversion when projecting result types.
Contextual information required for converting values are now passed on correctly when projecting id properties. Closes: #4524 Original pull request: #4525
1 parent 9c09edd commit 0474f65

File tree

2 files changed

+76
-1
lines changed

2 files changed

+76
-1
lines changed

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -578,7 +578,7 @@ private Object readIdValue(ConversionContext context, SpELExpressionEvaluator ev
578578
String expression = idProperty.getSpelExpression();
579579
Object resolvedValue = expression != null ? evaluator.evaluate(expression) : rawId;
580580

581-
return resolvedValue != null ? readValue(context, resolvedValue, idProperty.getTypeInformation()) : null;
581+
return resolvedValue != null ? readValue(context.forProperty(idProperty), resolvedValue, idProperty.getTypeInformation()) : null;
582582
}
583583

584584
private void readProperties(ConversionContext context, MongoPersistentEntity<?> entity,

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

+75
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@
3737
import org.junit.jupiter.api.Disabled;
3838
import org.junit.jupiter.api.Test;
3939
import org.junit.jupiter.api.extension.ExtendWith;
40+
import org.junit.jupiter.params.ParameterizedTest;
41+
import org.junit.jupiter.params.provider.ValueSource;
4042
import org.mockito.Mock;
4143
import org.mockito.Mockito;
4244
import org.mockito.junit.jupiter.MockitoExtension;
@@ -80,6 +82,7 @@
8082
import org.springframework.data.mongodb.core.mapping.FieldName.Type;
8183
import org.springframework.data.mongodb.core.mapping.FieldType;
8284
import org.springframework.data.mongodb.core.mapping.MongoField;
85+
import org.springframework.data.mongodb.core.mapping.MongoId;
8386
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
8487
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
8588
import org.springframework.data.mongodb.core.mapping.PersonPojoStringId;
@@ -2955,6 +2958,27 @@ void readShouldAllowDotsInMapKeyNameIfConfigured() {
29552958
assertThat(target.mapOfPersons).containsEntry("map.key.with.dots", person);
29562959
}
29572960

2961+
@ValueSource(classes = { ComplexIdAndNoAnnotation.class, ComplexIdAndIdAnnotation.class, ComplexIdAndMongoIdAnnotation.class, ComplexIdAndFieldAnnotation.class })
2962+
@ParameterizedTest // GH-4524
2963+
void projectShouldReadComplexIdType(Class<?> projectionTargetType) {
2964+
2965+
EntityProjectionIntrospector introspector = EntityProjectionIntrospector.create(converter.getProjectionFactory(),
2966+
EntityProjectionIntrospector.ProjectionPredicate.typeHierarchy()
2967+
.and((target, underlyingType) -> !converter.conversions.isSimpleType(target)),
2968+
mappingContext);
2969+
2970+
ComplexId idValue = ComplexId.of(101L);
2971+
org.bson.Document source = new org.bson.Document("_id", new org.bson.Document("innerId", idValue.innerId))
2972+
.append("value", "abc").append("_class", ComplexIdAndNoAnnotation.class.getName());
2973+
2974+
EntityProjection<?, ComplexIdAndNoAnnotation> projection = introspector.introspect(projectionTargetType,
2975+
ComplexIdAndNoAnnotation.class);
2976+
2977+
assertThat(converter.project(projection, source)) //
2978+
.isInstanceOf(projectionTargetType) //
2979+
.extracting("id").isEqualTo(idValue);
2980+
}
2981+
29582982
org.bson.Document write(Object source) {
29592983

29602984
org.bson.Document target = new org.bson.Document();
@@ -3219,7 +3243,33 @@ static class ClassWithComplexId {
32193243
}
32203244

32213245
static class ComplexId {
3246+
32223247
Long innerId;
3248+
3249+
static ComplexId of(Long value) {
3250+
3251+
ComplexId id = new ComplexId();
3252+
id.innerId = value;
3253+
return id;
3254+
}
3255+
3256+
@Override
3257+
public boolean equals(Object o) {
3258+
3259+
if (o == this) {
3260+
return true;
3261+
}
3262+
if (o == null || getClass() != o.getClass()) {
3263+
return false;
3264+
}
3265+
ComplexId complexId = (ComplexId) o;
3266+
return Objects.equals(innerId, complexId.innerId);
3267+
}
3268+
3269+
@Override
3270+
public int hashCode() {
3271+
return Objects.hash(innerId);
3272+
}
32233273
}
32243274

32253275
static class TypWithCollectionConstructor {
@@ -4031,7 +4081,32 @@ static class WithPropertyHavingDotsInFieldName {
40314081

40324082
@Field(name = "field.name.with.dots", nameType = Type.KEY)
40334083
String value;
4084+
}
4085+
4086+
static class ComplexIdAndFieldAnnotation {
4087+
4088+
@Field("_id") //
4089+
ComplexId id;
4090+
String value;
4091+
}
4092+
4093+
static class ComplexIdAndMongoIdAnnotation {
40344094

4095+
@MongoId //
4096+
ComplexId id;
4097+
String value;
40354098
}
40364099

4100+
static class ComplexIdAndIdAnnotation {
4101+
4102+
@Id //
4103+
ComplexId id;
4104+
String value;
4105+
}
4106+
4107+
static class ComplexIdAndNoAnnotation {
4108+
4109+
ComplexId id;
4110+
String value;
4111+
}
40374112
}

0 commit comments

Comments
 (0)