Skip to content

Commit 20eb0f4

Browse files
committed
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
1 parent 93d0e73 commit 20eb0f4

File tree

2 files changed

+43
-2
lines changed

2 files changed

+43
-2
lines changed

spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/convert/MappingCassandraConverter.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1427,11 +1427,11 @@ public <T> T getParameterValue(Parameter<T, CassandraPersistentProperty> paramet
14271427
name, entity.getType()));
14281428
}
14291429

1430-
return (T) getReadValue(context, provider, property);
1430+
return (T) getReadValue(context.forProperty(property.getName()), provider, property);
14311431
}
14321432

14331433
@Nullable
1434-
private <T> CassandraPersistentProperty getPersistentProperty(String name, TypeInformation<?> typeInformation,
1434+
private CassandraPersistentProperty getPersistentProperty(String name, TypeInformation<?> typeInformation,
14351435
MergedAnnotations annotations) {
14361436

14371437
CassandraPersistentProperty property = entity.getPersistentProperty(name);

spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/convert/MappingCassandraConverterUnitTests.java

+41
Original file line numberDiff line numberDiff line change
@@ -964,6 +964,33 @@ void shouldConsiderNestedProjections() {
964964
assertThat(result.getTuple().getOne()).isEqualTo("One");
965965
}
966966

967+
@Test // GH-1202
968+
void shouldCreateDtoProjectionsThroughConstructor() {
969+
970+
DefaultTupleValue value = new DefaultTupleValue(
971+
new DefaultTupleType(Arrays.asList(DataTypes.ASCII, DataTypes.ASCII, DataTypes.ASCII)));
972+
973+
value.setString(0, "Zero");
974+
value.setString(1, "One");
975+
value.setString(2, "Two");
976+
977+
EntityProjectionIntrospector introspector = EntityProjectionIntrospector.create(
978+
new SpelAwareProxyProjectionFactory(), EntityProjectionIntrospector.ProjectionPredicate.typeHierarchy(),
979+
this.mappingContext);
980+
981+
rowMock = RowMockUtil.newRowMock(RowMockUtil.column("firstname", "Heisenberg", DataTypes.ASCII),
982+
RowMockUtil.column("tuple", value, value.getType()));
983+
984+
EntityProjection<TupleAndNameProjection, WithMappedTuple> projection = introspector
985+
.introspect(TupleAndNameProjection.class, WithMappedTuple.class);
986+
987+
TupleAndNameProjection result = this.mappingCassandraConverter.project(projection, rowMock);
988+
989+
assertThat(result.getName().getFirstname()).isEqualTo("Heisenberg");
990+
assertThat(result.getTuple().zero).isEqualTo("Zero");
991+
assertThat(result.getTuple().one).isEqualTo("One");
992+
}
993+
967994
private static List<Object> getValues(Map<CqlIdentifier, Object> statement) {
968995
return new ArrayList<>(statement.values());
969996
}
@@ -1204,16 +1231,30 @@ public WithColumnAnnotationInConstructor(@Column("fn") String firstname, @Column
12041231
private static class WithMappedTuple {
12051232

12061233
String firstname;
1234+
@Embedded.Nullable Name name;
12071235
TupleWithElementAnnotationInConstructor tuple;
12081236
}
12091237

1238+
@lombok.Value
1239+
private static class Name {
1240+
String firstname;
1241+
}
1242+
12101243
@Data
12111244
private static class WithMappedTupleDtoProjection {
12121245

12131246
String firstname;
12141247
TupleProjection tuple;
12151248
}
12161249

1250+
@lombok.Value
1251+
private static class TupleAndNameProjection {
1252+
1253+
@Embedded.Nullable Name name;
1254+
1255+
TupleWithElementAnnotationInConstructor tuple;
1256+
}
1257+
12171258
private static interface TupleProjection {
12181259

12191260
String getZero();

0 commit comments

Comments
 (0)