程序员人生 网站导航

关于Spring JDBC RowMapper的一点改进思路

栏目:框架设计时间:2015-04-21 08:33:43

【注】通常我们使用RowMapper(比如ParameterizedRowMapper),都需要定义好查询字段,如果使用别名就没办法了。还要比如加入group,或联合查询,也不能够使用,除非不想要非主体Bean以外的字段,那末只能用Map接收返回结果了,或直接实现RowMapper。基于这1点,提出1个略微通用的解决思路:所有的Bean都继承1个基类Bean,里面放1个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); } }

该类中只放1个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)方法。个人感觉能够提高1定的便捷性,后续会加入sbrom中,关于sbrom可以查看http://blog.csdn.net/yefeng_918/article/details/44747033,欢迎吐槽!

------分隔线----------------------------
------分隔线----------------------------

最新技术推荐