Skip to content

Commit 39562bb

Browse files
committed
Consider full type descriptors in DataClassRowMapper.
Closes #1129
1 parent 5219184 commit 39562bb

File tree

3 files changed

+34
-9
lines changed

3 files changed

+34
-9
lines changed

spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/cql/BeanPropertyRowMapper.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,7 @@ protected Object getColumnValue(Row row, int index, PropertyDescriptor pd) {
389389
*/
390390
@Nullable
391391
protected Object getColumnValue(Row row, int index, Class<?> paramType) {
392-
return row.get(index, paramType);
392+
return row.getObject(index);
393393
}
394394

395395
/**

spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/cql/DataClassRowMapper.java

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@
1919

2020
import org.springframework.beans.BeanUtils;
2121
import org.springframework.beans.TypeConverter;
22+
import org.springframework.core.MethodParameter;
2223
import org.springframework.core.convert.ConversionService;
24+
import org.springframework.core.convert.TypeDescriptor;
2325
import org.springframework.lang.Nullable;
2426
import org.springframework.util.Assert;
2527

@@ -43,7 +45,7 @@ public class DataClassRowMapper<T> extends BeanPropertyRowMapper<T> {
4345

4446
private @Nullable String[] constructorParameterNames;
4547

46-
private @Nullable Class<?>[] constructorParameterTypes;
48+
private @Nullable TypeDescriptor[] constructorParameterTypes;
4749

4850
/**
4951
* Create a new {@code DataClassRowMapper}.
@@ -60,9 +62,13 @@ protected void initialize(Class<T> mappedClass) {
6062
super.initialize(mappedClass);
6163

6264
this.mappedConstructor = BeanUtils.getResolvableConstructor(mappedClass);
63-
if (this.mappedConstructor.getParameterCount() > 0) {
65+
int paramCount = this.mappedConstructor.getParameterCount();
66+
if (paramCount > 0) {
6467
this.constructorParameterNames = BeanUtils.getParameterNames(this.mappedConstructor);
65-
this.constructorParameterTypes = this.mappedConstructor.getParameterTypes();
68+
this.constructorParameterTypes = new TypeDescriptor[paramCount];
69+
for (int i = 0; i < paramCount; i++) {
70+
this.constructorParameterTypes[i] = new TypeDescriptor(new MethodParameter(this.mappedConstructor, i));
71+
}
6672
}
6773
}
6874

@@ -76,8 +82,9 @@ protected T constructMappedInstance(Row row, TypeConverter tc) {
7682
args = new Object[this.constructorParameterNames.length];
7783
for (int i = 0; i < args.length; i++) {
7884
String name = underscoreName(this.constructorParameterNames[i]);
79-
Class<?> type = this.constructorParameterTypes[i];
80-
args[i] = tc.convertIfNecessary(getColumnValue(row, row.getColumnDefinitions().firstIndexOf(name), type), type);
85+
TypeDescriptor td = this.constructorParameterTypes[i];
86+
Object value = getColumnValue(row, row.getColumnDefinitions().firstIndexOf(name), td.getType());
87+
args[i] = tc.convertIfNecessary(value, td.getType(), td);
8188
}
8289
} else {
8390
args = new Object[0];

spring-data-cassandra/src/test/kotlin/org/springframework/data/cassandra/core/cql/DataClassRowMapperUnitTests.kt

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ class DataClassRowMapperUnitTests {
4040
val definitions = forColumns("firstname", "age")
4141

4242
every { row.columnDefinitions } returns definitions
43-
every { row.get(0, String::class.java) } returns "Walter"
44-
every { row.get(1, Int::class.javaPrimitiveType) } returns 42
43+
every { row.getObject(0) } returns "Walter"
44+
every { row.getObject(1) } returns 42
4545

4646
val rowMapper = DataClassRowMapper<Person>()
4747
val person = rowMapper.mapRow(row, 0)
@@ -50,7 +50,24 @@ class DataClassRowMapperUnitTests {
5050
assertThat(person.age).isEqualTo(42)
5151
}
5252

53+
@Test // #1129
54+
fun createBeanWithGenericsFromRow() {
55+
56+
val definitions = forColumns("firstname", "age")
57+
58+
every { row.columnDefinitions } returns definitions
59+
every { row.getObject(0) } returns "Walter"
60+
every { row.getObject(1) } returns 42
61+
62+
val rowMapper = DataClassRowMapper<PersonWithAgeList>()
63+
val person = rowMapper.mapRow(row, 0)
64+
65+
assertThat(person.firstname).isEqualTo("Walter")
66+
assertThat(person.age).contains(42)
67+
}
68+
5369
data class Person(val firstname: String, val age: Int)
70+
data class PersonWithAgeList(val firstname: String, val age: List<Int>)
5471

5572
private fun forColumns(vararg columns: String): ColumnDefinitions {
5673

@@ -59,7 +76,8 @@ class DataClassRowMapperUnitTests {
5976
for (column in columns) {
6077
val columnDefinition = Mockito.mock(ColumnDefinition::class.java)
6178
val columnIndex = index++
62-
Mockito.`when`(columnDefinition.name).thenReturn(CqlIdentifier.fromInternal(column))
79+
Mockito.`when`(columnDefinition.name)
80+
.thenReturn(CqlIdentifier.fromInternal(column))
6381
Mockito.`when`(definitions[columnIndex]).thenReturn(columnDefinition)
6482
Mockito.`when`(definitions.firstIndexOf(column)).thenReturn(columnIndex)
6583
}

0 commit comments

Comments
 (0)