Updated BeanPropertyRowMapper to remove spaces from column names to improve matching to properties (SPR-5758)

git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@1302 50f2f4bb-b051-0410-bef5-90022cba6387
This commit is contained in:
Thomas Risberg 2009-06-02 20:58:44 +00:00
parent 7c9b459aa5
commit 35d527f756
4 changed files with 167 additions and 4 deletions

View File

@ -236,8 +236,8 @@ public class BeanPropertyRowMapper<T> implements RowMapper<T> {
Set<String> populatedProperties = (isCheckFullyPopulated() ? new HashSet<String>() : null); Set<String> populatedProperties = (isCheckFullyPopulated() ? new HashSet<String>() : null);
for (int index = 1; index <= columnCount; index++) { for (int index = 1; index <= columnCount; index++) {
String column = JdbcUtils.lookupColumnName(rsmd, index).toLowerCase(); String column = JdbcUtils.lookupColumnName(rsmd, index);
PropertyDescriptor pd = this.mappedFields.get(column); PropertyDescriptor pd = this.mappedFields.get(column.replaceAll(" ", "").toLowerCase());
if (pd != null) { if (pd != null) {
try { try {
Object value = getColumnValue(rs, index, pd); Object value = getColumnValue(rs, index, pd);

View File

@ -31,6 +31,7 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.jdbc.core.test.ConcretePerson; import org.springframework.jdbc.core.test.ConcretePerson;
import org.springframework.jdbc.core.test.Person; import org.springframework.jdbc.core.test.Person;
import org.springframework.jdbc.core.test.SpacePerson;
import org.springframework.jdbc.datasource.SingleConnectionDataSource; import org.springframework.jdbc.datasource.SingleConnectionDataSource;
import org.springframework.jdbc.support.SQLStateSQLExceptionTranslator; import org.springframework.jdbc.support.SQLStateSQLExceptionTranslator;
@ -48,6 +49,9 @@ public abstract class AbstractRowMapperTests extends TestCase {
protected Connection con; protected Connection con;
protected MockControl conControl2; protected MockControl conControl2;
protected Connection con2; protected Connection con2;
protected MockControl conControl3;
protected Connection con3;
protected MockControl rsmdControl; protected MockControl rsmdControl;
protected ResultSetMetaData rsmd; protected ResultSetMetaData rsmd;
protected MockControl rsControl; protected MockControl rsControl;
@ -55,6 +59,7 @@ public abstract class AbstractRowMapperTests extends TestCase {
protected MockControl stmtControl; protected MockControl stmtControl;
protected Statement stmt; protected Statement stmt;
protected JdbcTemplate jdbcTemplate; protected JdbcTemplate jdbcTemplate;
protected MockControl rsmdControl2; protected MockControl rsmdControl2;
protected ResultSetMetaData rsmd2; protected ResultSetMetaData rsmd2;
protected MockControl rsControl2; protected MockControl rsControl2;
@ -63,6 +68,14 @@ public abstract class AbstractRowMapperTests extends TestCase {
protected Statement stmt2; protected Statement stmt2;
protected JdbcTemplate jdbcTemplate2; protected JdbcTemplate jdbcTemplate2;
protected MockControl rsmdControl3;
protected ResultSetMetaData rsmd3;
protected MockControl rsControl3;
protected ResultSet rs3;
protected MockControl stmtControl3;
protected Statement stmt3;
protected JdbcTemplate jdbcTemplate3;
protected void setUp() throws SQLException { protected void setUp() throws SQLException {
conControl = MockControl.createControl(Connection.class); conControl = MockControl.createControl(Connection.class);
con = (Connection) conControl.getMock(); con = (Connection) conControl.getMock();
@ -119,6 +132,9 @@ public abstract class AbstractRowMapperTests extends TestCase {
stmt.close(); stmt.close();
stmtControl.setVoidCallable(1); stmtControl.setVoidCallable(1);
conControl.replay();
stmtControl.replay();
conControl2 = MockControl.createControl(Connection.class); conControl2 = MockControl.createControl(Connection.class);
con2 = (Connection) conControl2.getMock(); con2 = (Connection) conControl2.getMock();
con2.isClosed(); con2.isClosed();
@ -174,11 +190,67 @@ public abstract class AbstractRowMapperTests extends TestCase {
stmt2.close(); stmt2.close();
stmtControl2.setVoidCallable(2); stmtControl2.setVoidCallable(2);
conControl.replay();
stmtControl.replay();
conControl2.replay(); conControl2.replay();
stmtControl2.replay(); stmtControl2.replay();
conControl3 = MockControl.createControl(Connection.class);
con3 = (Connection) conControl3.getMock();
con3.isClosed();
conControl3.setDefaultReturnValue(false);
rsmdControl3 = MockControl.createControl(ResultSetMetaData.class);
rsmd3 = (ResultSetMetaData)rsmdControl3.getMock();
rsmd3.getColumnCount();
rsmdControl3.setReturnValue(4, 1);
rsmd3.getColumnLabel(1);
rsmdControl3.setReturnValue("Last Name", 1);
rsmd3.getColumnLabel(2);
rsmdControl3.setReturnValue("age", 1);
rsmd3.getColumnLabel(3);
rsmdControl3.setReturnValue("birth_date", 1);
rsmd3.getColumnLabel(4);
rsmdControl3.setReturnValue("balance", 1);
rsmdControl3.replay();
rsControl3 = MockControl.createControl(ResultSet.class);
rs3 = (ResultSet) rsControl3.getMock();
rs3.getMetaData();
rsControl3.setReturnValue(rsmd3, 1);
rs3.next();
rsControl3.setReturnValue(true, 1);
rs3.getString(1);
rsControl3.setReturnValue("Gagarin", 1);
rs3.wasNull();
rsControl3.setReturnValue(false, 1);
rs3.getLong(2);
rsControl3.setReturnValue(22, 1);
rs3.getTimestamp(3);
rsControl3.setReturnValue(new Timestamp(1221222L), 1);
rs3.getBigDecimal(4);
rsControl3.setReturnValue(new BigDecimal("1234.56"), 1);
rs3.next();
rsControl3.setReturnValue(false, 1);
rs3.close();
rsControl3.setVoidCallable(1);
rsControl3.replay();
stmtControl3 = MockControl.createControl(Statement.class);
stmt3 = (Statement) stmtControl3.getMock();
con3.createStatement();
conControl3.setReturnValue(stmt3, 1);
stmt3.executeQuery("select last_name as \"Last Name\", age, birth_date, balance from people");
stmtControl3.setReturnValue(rs3, 1);
if (debugEnabled) {
stmt3.getWarnings();
stmtControl3.setReturnValue(null, 1);
}
stmt3.close();
stmtControl3.setVoidCallable(1);
conControl3.replay();
stmtControl3.replay();
jdbcTemplate = new JdbcTemplate(); jdbcTemplate = new JdbcTemplate();
jdbcTemplate.setDataSource(new SingleConnectionDataSource(con, false)); jdbcTemplate.setDataSource(new SingleConnectionDataSource(con, false));
jdbcTemplate.setExceptionTranslator(new SQLStateSQLExceptionTranslator()); jdbcTemplate.setExceptionTranslator(new SQLStateSQLExceptionTranslator());
@ -188,6 +260,11 @@ public abstract class AbstractRowMapperTests extends TestCase {
jdbcTemplate2.setDataSource(new SingleConnectionDataSource(con2, false)); jdbcTemplate2.setDataSource(new SingleConnectionDataSource(con2, false));
jdbcTemplate2.setExceptionTranslator(new SQLStateSQLExceptionTranslator()); jdbcTemplate2.setExceptionTranslator(new SQLStateSQLExceptionTranslator());
jdbcTemplate2.afterPropertiesSet(); jdbcTemplate2.afterPropertiesSet();
jdbcTemplate3 = new JdbcTemplate();
jdbcTemplate3.setDataSource(new SingleConnectionDataSource(con3, false));
jdbcTemplate3.setExceptionTranslator(new SQLStateSQLExceptionTranslator());
jdbcTemplate3.afterPropertiesSet();
} }
protected void verifyPerson(Person bean) { protected void verifyPerson(Person bean) {
@ -217,6 +294,17 @@ public abstract class AbstractRowMapperTests extends TestCase {
assertEquals(new BigDecimal("1234.56"), bean.getBalance()); assertEquals(new BigDecimal("1234.56"), bean.getBalance());
} }
protected void verifySpacePerson(SpacePerson bean) {
conControl3.verify();
rsControl3.verify();
rsmdControl3.verify();
stmtControl3.verify();
assertEquals("Gagarin", bean.getLastName());
assertEquals(22L, bean.getAge());
assertEquals(new java.util.Date(1221222L), bean.getBirthDate());
assertEquals(new BigDecimal("1234.56"), bean.getBalance());
}
private void verify() { private void verify() {
conControl.verify(); conControl.verify();
rsControl.verify(); rsControl.verify();

View File

@ -23,6 +23,7 @@ import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.jdbc.core.test.ConcretePerson; import org.springframework.jdbc.core.test.ConcretePerson;
import org.springframework.jdbc.core.test.ExtendedPerson; import org.springframework.jdbc.core.test.ExtendedPerson;
import org.springframework.jdbc.core.test.Person; import org.springframework.jdbc.core.test.Person;
import org.springframework.jdbc.core.test.SpacePerson;
import org.springframework.beans.TypeMismatchException; import org.springframework.beans.TypeMismatchException;
/** /**
@ -108,4 +109,12 @@ public class BeanPropertyRowMapperTests extends AbstractRowMapperTests {
verifyPersonWithZeroAge(bean); verifyPersonWithZeroAge(bean);
} }
public void testQueryWithSpaceInColumnName() throws SQLException {
List result = jdbcTemplate3.query("select last_name as \"Last Name\", age, birth_date, balance from people",
new BeanPropertyRowMapper(SpacePerson.class));
assertEquals(1, result.size());
SpacePerson bean = (SpacePerson) result.get(0);
verifySpacePerson(bean);
}
} }

View File

@ -0,0 +1,66 @@
/*
* Copyright 2002-2008 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.jdbc.core.test;
import java.math.BigDecimal;
/**
* @author Thomas Risberg
*/
public class SpacePerson {
private String lastName;
private long age;
private java.util.Date birthDate;
private BigDecimal balance;
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public long getAge() {
return age;
}
public void setAge(long age) {
this.age = age;
}
public java.util.Date getBirthDate() {
return birthDate;
}
public void setBirth_date(java.util.Date birthDate) {
this.birthDate = birthDate;
}
public BigDecimal getBalance() {
return balance;
}
public void setBalance(BigDecimal balanace) {
this.balance = balanace;
}
}