Consistent support for direct column matches in DataClassRowMapper

Closes gh-28243
This commit is contained in:
Juergen Hoeller 2022-04-08 13:00:31 +02:00
parent 0cf15c0fdd
commit 90103b0ae9
8 changed files with 69 additions and 35 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -98,9 +98,18 @@ public class DataClassRowMapper<T> extends BeanPropertyRowMapper<T> {
if (this.constructorParameterNames != null && this.constructorParameterTypes != null) {
args = new Object[this.constructorParameterNames.length];
for (int i = 0; i < args.length; i++) {
String name = underscoreName(this.constructorParameterNames[i]);
String name = this.constructorParameterNames[i];
int index;
try {
// Try direct name match first
index = rs.findColumn(lowerCaseName(name));
}
catch (SQLException ex) {
// Try underscored name match instead
index = rs.findColumn(underscoreName(name));
}
TypeDescriptor td = this.constructorParameterTypes[i];
Object value = getColumnValue(rs, rs.findColumn(name), td.getType());
Object value = getColumnValue(rs, index, td.getType());
args[i] = tc.convertIfNecessary(value, td.getType(), td);
}
}

View File

@ -20,6 +20,7 @@ import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.sql.Statement;
import java.sql.Timestamp;
@ -63,7 +64,7 @@ public abstract class AbstractRowMapperTests {
protected void verifyPerson(ConcretePerson person) {
assertThat(person.getName()).isEqualTo("Bubba");
assertThat(person.getAge()).isEqualTo(22L);
assertThat(person.getBirth_date()).usingComparator(Date::compareTo).isEqualTo(new java.util.Date(1221222L));
assertThat(person.getBirthDate()).usingComparator(Date::compareTo).isEqualTo(new java.util.Date(1221222L));
assertThat(person.getBalance()).isEqualTo(new BigDecimal("1234.56"));
verifyPersonViaBeanWrapper(person);
}
@ -94,7 +95,14 @@ public abstract class AbstractRowMapperTests {
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(person);
assertThat(bw.getPropertyValue("name")).isEqualTo("Bubba");
assertThat(bw.getPropertyValue("age")).isEqualTo(22L);
assertThat((Date) bw.getPropertyValue("birth_date")).usingComparator(Date::compareTo).isEqualTo(new java.util.Date(1221222L));
Date birthDate;
if (bw.isReadableProperty("birth_date")) {
birthDate = (Date) bw.getPropertyValue("birth_date");
}
else {
birthDate = (Date) bw.getPropertyValue("birthDate");
}
assertThat(birthDate).usingComparator(Date::compareTo).isEqualTo(new java.util.Date(1221222L));
assertThat(bw.getPropertyValue("balance")).isEqualTo(new BigDecimal("1234.56"));
}
@ -107,7 +115,7 @@ public abstract class AbstractRowMapperTests {
}
protected enum MockType {ONE, TWO, THREE}
protected enum MockType {ONE, TWO, THREE, FOUR}
protected static class Mock {
@ -152,13 +160,19 @@ public abstract class AbstractRowMapperTests {
given(resultSetMetaData.getColumnLabel(1)).willReturn(
type == MockType.THREE ? "Last Name" : "name");
given(resultSetMetaData.getColumnLabel(2)).willReturn("age");
given(resultSetMetaData.getColumnLabel(3)).willReturn("birth_date");
given(resultSetMetaData.getColumnLabel(3)).willReturn(type == MockType.FOUR ? "birthdate" :"birth_date");
given(resultSetMetaData.getColumnLabel(4)).willReturn("balance");
given(resultSetMetaData.getColumnLabel(5)).willReturn("e_mail");
given(resultSet.findColumn("name")).willReturn(1);
given(resultSet.findColumn("age")).willReturn(2);
given(resultSet.findColumn("birth_date")).willReturn(3);
if (type == MockType.FOUR) {
given(resultSet.findColumn("birthdate")).willReturn(3);
}
else {
given(resultSet.findColumn("birthdate")).willThrow(new SQLException());
given(resultSet.findColumn("birth_date")).willReturn(3);
}
given(resultSet.findColumn("balance")).willReturn(4);
given(resultSet.findColumn("e_mail")).willReturn(5);

View File

@ -140,6 +140,17 @@ class BeanPropertyRowMapperTests extends AbstractRowMapperTests {
mock.verifyClosed();
}
@Test
void queryWithDirectNameMatchOnBirthDate() throws Exception {
Mock mock = new Mock(MockType.FOUR);
List<ConcretePerson> result = mock.getJdbcTemplate().query(
"select name, age, birthdate, balance from people",
new BeanPropertyRowMapper<>(ConcretePerson.class));
assertThat(result).hasSize(1);
verifyPerson(result.get(0));
mock.verifyClosed();
}
@Test
void queryWithUnderscoreInColumnNameAndPersonWithMultipleAdjacentUppercaseLettersInPropertyName() throws Exception {
Mock mock = new Mock();

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -57,7 +57,7 @@ public class DataClassRowMapperTests extends AbstractRowMapperTests {
ConstructorPersonWithGenerics person = result.get(0);
assertThat(person.name()).isEqualTo("Bubba");
assertThat(person.age()).isEqualTo(22L);
assertThat(person.birth_date()).usingComparator(Date::compareTo).isEqualTo(new java.util.Date(1221222L));
assertThat(person.birthDate()).usingComparator(Date::compareTo).isEqualTo(new java.util.Date(1221222L));
assertThat(person.balance()).isEqualTo(Collections.singletonList(new BigDecimal("1234.56")));
mock.verifyClosed();
@ -65,15 +65,15 @@ public class DataClassRowMapperTests extends AbstractRowMapperTests {
@Test
public void testStaticQueryWithDataClassAndSetters() throws Exception {
Mock mock = new Mock();
Mock mock = new Mock(MockType.FOUR);
List<ConstructorPersonWithSetters> result = mock.getJdbcTemplate().query(
"select name, age, birth_date, balance from people",
"select name, age, birthdate, balance from people",
new DataClassRowMapper<>(ConstructorPersonWithSetters.class));
assertThat(result.size()).isEqualTo(1);
ConstructorPersonWithSetters person = result.get(0);
assertThat(person.name()).isEqualTo("BUBBA");
assertThat(person.age()).isEqualTo(22L);
assertThat(person.birth_date()).usingComparator(Date::compareTo).isEqualTo(new java.util.Date(1221222L));
assertThat(person.birthDate()).usingComparator(Date::compareTo).isEqualTo(new java.util.Date(1221222L));
assertThat(person.balance()).isEqualTo(new BigDecimal("1234.56"));
mock.verifyClosed();

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -27,7 +27,7 @@ public abstract class AbstractPerson {
private long age;
private Date birth_date;
private Date birthDate;
public String getName() {
@ -46,12 +46,12 @@ public abstract class AbstractPerson {
this.age = age;
}
public Date getBirth_date() {
return birth_date;
public Date getBirthDate() {
return birthDate;
}
public void setBirth_date(Date birth_date) {
this.birth_date = birth_date;
public void setBirthDate(Date birthDate) {
this.birthDate = birthDate;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -29,7 +29,7 @@ public class ConstructorPersonWithGenerics {
private final long age;
private final Date birth_date;
private final Date birthDate;
private final List<BigDecimal> balance;
@ -37,7 +37,7 @@ public class ConstructorPersonWithGenerics {
public ConstructorPersonWithGenerics(String name, long age, Date birth_date, List<BigDecimal> balance) {
this.name = name;
this.age = age;
this.birth_date = birth_date;
this.birthDate = birth_date;
this.balance = balance;
}
@ -50,8 +50,8 @@ public class ConstructorPersonWithGenerics {
return this.age;
}
public Date birth_date() {
return this.birth_date;
public Date birthDate() {
return this.birthDate;
}
public List<BigDecimal> balance() {

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -28,15 +28,15 @@ public class ConstructorPersonWithSetters {
private long age;
private Date birth_date;
private Date birthDate;
private BigDecimal balance;
public ConstructorPersonWithSetters(String name, long age, Date birth_date, BigDecimal balance) {
public ConstructorPersonWithSetters(String name, long age, Date birthDate, BigDecimal balance) {
this.name = name.toUpperCase();
this.age = age;
this.birth_date = birth_date;
this.birthDate = birthDate;
this.balance = balance;
}
@ -49,8 +49,8 @@ public class ConstructorPersonWithSetters {
this.age = age;
}
public void setBirth_date(Date birth_date) {
this.birth_date = birth_date;
public void setBirthDate(Date birthDate) {
this.birthDate = birthDate;
}
public void setBalance(BigDecimal balance) {
@ -65,8 +65,8 @@ public class ConstructorPersonWithSetters {
return this.age;
}
public Date birth_date() {
return this.birth_date;
public Date birthDate() {
return this.birthDate;
}
public BigDecimal balance() {

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -60,8 +60,8 @@ public class SpacePerson {
return balance;
}
public void setBalance(BigDecimal balanace) {
this.balance = balanace;
public void setBalance(BigDecimal balance) {
this.balance = balance;
}
}