【注】通常我们使用RowMapper(比如ParameterizedRowMapper),都需要定义好查询字段,如果使用别名就没办法了。还要比如加入group,或者联合查询,也不能够使用,除非不想要非主体Bean之外的字段,那么只能用Map接收返回结果了,或者直接实现RowMapper。基于这一点,提出一个稍微通用的解决思路:所有的Bean都继承一个基类Bean,里面放一个Map(就是存放那些Bean没有指定的字段了,比如sum、count、avg … 各种查询字段或者别名),参考BeanPropertyRowMapper,在mapRow方法里面做些小调整,找不到的column就放到map里面,这样子的话,Bean有的字段就采用getxxx(),没有就从map里面取,好像会有点用。
#具体方法如下#
public abstract class BaseEntity {
private Map<String, Object> aliasFields = new HashMap<String, Object>();
public void setAliasField(String field, Object value) {
aliasFields.put(field, value);
}
public Object getAliasFields(String field) {
return aliasFields.get(field);
}
}
该类中只放一个map,存储Bean里面没有的字段,剩下的就是改造RowMapper实现类,可以拷贝BeanPropertyRowMapper,换个类名,直接修改mapRow方法,具体如下(改动量非常小,看注释):
public T mapRow(ResultSet rs, int rowNumber) throws SQLException {
Assert.state(this.mappedClass != null, "Mapped class was not specified");
T mappedObject = BeanUtils.instantiate(this.mappedClass);
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(mappedObject);
initBeanWrapper(bw);
ResultSetMetaData rsmd = rs.getMetaData();
int columnCount = rsmd.getColumnCount();
Set<String> populatedProperties = (isCheckFullyPopulated() ? new HashSet<String>() : null);
for (int index = 1; index <= columnCount; index++) {
String column = JdbcUtils.lookupColumnName(rsmd, index);
PropertyDescriptor pd = this.mappedFields.get(column.replaceAll(" ", "").toLowerCase());
if (pd != null) {
try {
Object value = getColumnValue(rs, index, pd);
if (logger.isDebugEnabled() && rowNumber == 0) {
logger.debug("Mapping column ‘" + column + "‘ to property ‘" +
pd.getName() + "‘ of type " + pd.getPropertyType());
}
try {
bw.setPropertyValue(pd.getName(), value);
}
catch (TypeMismatchException e) {
if (value == null && primitivesDefaultedForNullValue) {
logger.debug("Intercepted TypeMismatchException for row " + rowNumber +
" and column ‘" + column + "‘ with value " + value +
" when setting property ‘" + pd.getName() + "‘ of type " + pd.getPropertyType() +
" on object: " + mappedObject);
}
else {
throw e;
}
}
if (populatedProperties != null) {
populatedProperties.add(pd.getName());
}
}
catch (NotWritablePropertyException ex) {
throw new DataRetrievalFailureException(
"Unable to map column " + column + " to property " + pd.getName(), ex);
}
} else {/// *****就是修改这个地方了!!!!
Object value = JdbcUtils.getResultSetValue(rs, index);
((BaseEntity)mappedObject).setAliasField(column, value);
}
}
if (populatedProperties != null && !populatedProperties.equals(this.mappedProperties)) {
throw new InvalidDataAccessApiUsageException("Given ResultSet does not contain all fields " +
"necessary to populate object of class [" + this.mappedClass + "]: " + this.mappedProperties);
}
return mappedObject;
}
剩下的就是具体的Bean,继承BaseEntity,比如:
public class Demo extends BaseEntity implements Serializable {
public static final long serialVersionUID = 2233912281609962999L;
private Integer id;
private String name;
private String password;
private Date createTime;
private Integer type;
public Demo() {
super.queryBuilder = new QueryBuilder(this);
}
public void setId (Integer id) {
this.id = id;
}
public Integer getId () {
return this.id;
}
public void setName (String name) {
this.name = name;
}
public String getName () {
return this.name;
}
public void setPassword (String password) {
this.password = password;
}
public String getPassword () {
return this.password;
}
public void setCreateTime (Date createTime) {
this.createTime = createTime;
}
public Date getCreateTime () {
return this.createTime;
}
public void setType (Integer type) {
this.type = type;
}
public Integer getType () {
return this.type;
}
}
查询的时候,就可以通过Demo Bean取出非表字段的数据,通过getAliasFields(String field)方法。个人感觉能够提高一定的便捷性,后续会加入sbrom中,关于sbrom可以查看http://blog.csdn.net/yefeng_918/article/details/44747033,欢迎吐槽!
关于Spring JDBC RowMapper的一点改进思路
原文:http://blog.csdn.net/yefeng_918/article/details/44947459