Skip to content

Commit 06e46a0

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 7b95d68 commit 06e46a0

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
@@ -1466,11 +1466,11 @@ public <T> T getParameterValue(Parameter<T, CassandraPersistentProperty> paramet
14661466
name, entity.getType()));
14671467
}
14681468

1469-
return (T) getReadValue(context, provider, property);
1469+
return (T) getReadValue(context.forProperty(property.getName()), provider, property);
14701470
}
14711471

14721472
@Nullable
1473-
private <T> CassandraPersistentProperty getPersistentProperty(String name, TypeInformation<?> typeInformation,
1473+
private CassandraPersistentProperty getPersistentProperty(String name, TypeInformation<?> typeInformation,
14741474
MergedAnnotations annotations) {
14751475

14761476
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
@@ -1078,6 +1078,33 @@ void shouldConsiderNestedProjections() {
10781078
assertThat(result.getTuple().getOne()).isEqualTo("One");
10791079
}
10801080

1081+
@Test // GH-1202
1082+
void shouldCreateDtoProjectionsThroughConstructor() {
1083+
1084+
DefaultTupleValue value = new DefaultTupleValue(
1085+
new DefaultTupleType(Arrays.asList(DataTypes.ASCII, DataTypes.ASCII, DataTypes.ASCII)));
1086+
1087+
value.setString(0, "Zero");
1088+
value.setString(1, "One");
1089+
value.setString(2, "Two");
1090+
1091+
EntityProjectionIntrospector introspector = EntityProjectionIntrospector.create(
1092+
new SpelAwareProxyProjectionFactory(), EntityProjectionIntrospector.ProjectionPredicate.typeHierarchy(),
1093+
this.mappingContext);
1094+
1095+
rowMock = RowMockUtil.newRowMock(RowMockUtil.column("firstname", "Heisenberg", DataTypes.ASCII),
1096+
RowMockUtil.column("tuple", value, value.getType()));
1097+
1098+
EntityProjection<TupleAndNameProjection, WithMappedTuple> projection = introspector
1099+
.introspect(TupleAndNameProjection.class, WithMappedTuple.class);
1100+
1101+
TupleAndNameProjection result = this.mappingCassandraConverter.project(projection, rowMock);
1102+
1103+
assertThat(result.getName().getFirstname()).isEqualTo("Heisenberg");
1104+
assertThat(result.getTuple().zero).isEqualTo("Zero");
1105+
assertThat(result.getTuple().one).isEqualTo("One");
1106+
}
1107+
10811108
private static List<Object> getValues(Map<CqlIdentifier, Object> statement) {
10821109
return new ArrayList<>(statement.values());
10831110
}
@@ -1340,16 +1367,30 @@ public WithColumnAnnotationInConstructor(@Column("fn") String firstname, @Column
13401367
private static class WithMappedTuple {
13411368

13421369
String firstname;
1370+
@Embedded.Nullable Name name;
13431371
TupleWithElementAnnotationInConstructor tuple;
13441372
}
13451373

1374+
@lombok.Value
1375+
private static class Name {
1376+
String firstname;
1377+
}
1378+
13461379
@Data
13471380
private static class WithMappedTupleDtoProjection {
13481381

13491382
String firstname;
13501383
TupleProjection tuple;
13511384
}
13521385

1386+
@lombok.Value
1387+
private static class TupleAndNameProjection {
1388+
1389+
@Embedded.Nullable Name name;
1390+
1391+
TupleWithElementAnnotationInConstructor tuple;
1392+
}
1393+
13531394
private static interface TupleProjection {
13541395

13551396
String getZero();

0 commit comments

Comments
 (0)