Fix DTO projection instantiation.

We now correctly instantiate DTO projection classes by using the actual constructor argument type. Previously, we did not update the conversion context to fetch the correct type but used the type of the DTO projection class instead of the constructor argument.

Closes #1292
This commit is contained in:
Mark Paluch
2022-07-19 11:42:25 +02:00
parent 93d0e73e29
commit 20eb0f47fa
2 changed files with 43 additions and 2 deletions

View File

@@ -1427,11 +1427,11 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
name, entity.getType()));
}
return (T) getReadValue(context, provider, property);
return (T) getReadValue(context.forProperty(property.getName()), provider, property);
}
@Nullable
private <T> CassandraPersistentProperty getPersistentProperty(String name, TypeInformation<?> typeInformation,
private CassandraPersistentProperty getPersistentProperty(String name, TypeInformation<?> typeInformation,
MergedAnnotations annotations) {
CassandraPersistentProperty property = entity.getPersistentProperty(name);

View File

@@ -964,6 +964,33 @@ public class MappingCassandraConverterUnitTests {
assertThat(result.getTuple().getOne()).isEqualTo("One");
}
@Test // GH-1202
void shouldCreateDtoProjectionsThroughConstructor() {
DefaultTupleValue value = new DefaultTupleValue(
new DefaultTupleType(Arrays.asList(DataTypes.ASCII, DataTypes.ASCII, DataTypes.ASCII)));
value.setString(0, "Zero");
value.setString(1, "One");
value.setString(2, "Two");
EntityProjectionIntrospector introspector = EntityProjectionIntrospector.create(
new SpelAwareProxyProjectionFactory(), EntityProjectionIntrospector.ProjectionPredicate.typeHierarchy(),
this.mappingContext);
rowMock = RowMockUtil.newRowMock(RowMockUtil.column("firstname", "Heisenberg", DataTypes.ASCII),
RowMockUtil.column("tuple", value, value.getType()));
EntityProjection<TupleAndNameProjection, WithMappedTuple> projection = introspector
.introspect(TupleAndNameProjection.class, WithMappedTuple.class);
TupleAndNameProjection result = this.mappingCassandraConverter.project(projection, rowMock);
assertThat(result.getName().getFirstname()).isEqualTo("Heisenberg");
assertThat(result.getTuple().zero).isEqualTo("Zero");
assertThat(result.getTuple().one).isEqualTo("One");
}
private static List<Object> getValues(Map<CqlIdentifier, Object> statement) {
return new ArrayList<>(statement.values());
}
@@ -1204,9 +1231,15 @@ public class MappingCassandraConverterUnitTests {
private static class WithMappedTuple {
String firstname;
@Embedded.Nullable Name name;
TupleWithElementAnnotationInConstructor tuple;
}
@lombok.Value
private static class Name {
String firstname;
}
@Data
private static class WithMappedTupleDtoProjection {
@@ -1214,6 +1247,14 @@ public class MappingCassandraConverterUnitTests {
TupleProjection tuple;
}
@lombok.Value
private static class TupleAndNameProjection {
@Embedded.Nullable Name name;
TupleWithElementAnnotationInConstructor tuple;
}
private static interface TupleProjection {
String getZero();