与原始类型的反射映射

时间:2016-06-02 13:55:32

标签: java jdbc reflection mapping

我需要一个可嵌套的bean rowmapper用于JDBC,我用过:

public class NestedRowMapper<T> implements RowMapper<T> {

    private static Logger log = LoggerFactory.getLogger(NestedRowMapper.class);

      private Class<T> mappedClass;

      public NestedRowMapper(Class<T> mappedClass) {
        this.mappedClass = mappedClass;
      }

      @Override
      public T mapRow(ResultSet rs, int rowNum) throws SQLException {

        T mappedObject = BeanUtils.instantiate(this.mappedClass);
        BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(mappedObject);

        bw.setAutoGrowNestedPaths(true);

        ResultSetMetaData meta_data = rs.getMetaData();
        int columnCount = meta_data.getColumnCount();

        for (int index = 1; index <= columnCount; index++) {

          String column=null;
          Object value=null;
          try {

            column = JdbcUtils.lookupColumnName(meta_data, index);
            value = JdbcUtils.getResultSetValue(rs, index, Class.forName(meta_data.getColumnClassName(index)));

            bw.setPropertyValue(column, value);

          } catch (TypeMismatchException | NotWritablePropertyException | ClassNotFoundException e) {
              log.error("",column,value,bw.getClass().getSimpleName(),e);
          }
        }

        return mappedObject;
      }
    }

除非找到原始类型,否则BeanWrapper.setPropertyValue会失败。

例如,如果在我的映射bean中有布尔(基元)而不是布尔(类)属性,则它会失败。如何更正它以使其映射原始类型属性?

2 个答案:

答案 0 :(得分:1)

我认为您可以检查源代码org.springframework.jdbc.core.BeanPropertyRowMapper,您需要从java类定义获取类类型,而不是从ResultSet元数据中获取。

例如,使用以下方法getClass(column)替换Class.forName(meta_data.getColumnClassName(index)

private Class<?> getClass(String column) {
    PropertyDescriptor[] pds = BeanUtils.getPropertyDescriptors(this.mappedClass);
    for (PropertyDescriptor pd : pds) {
        if (pd.getName().equals(column)) {
            return pd.getPropertyType();
        }
    }
    return null;
}

它只是一个例子,你需要像BeanPropertyRowMapper

那样进行缓存/尝试捕获

答案 1 :(得分:0)

这可以是带有andy解决方案的缓存版本,具有固定的嵌套属性查找。

public class NestedRowMapper<T> implements RowMapper<T> {

      private Class<T> mappedClass;
      private Map<String, Class<?>> mappedFields=new HashMap<String, Class<?>>();

      public NestedRowMapper(Class<T> mappedClass) {
        this.mappedClass = mappedClass;
      }

      @Override
      public T mapRow(ResultSet rs, int rowNum) throws SQLException {



        T mappedObject = BeanUtils.instantiate(this.mappedClass);
        BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(mappedObject);

        bw.setAutoGrowNestedPaths(true);

        ResultSetMetaData meta_data = rs.getMetaData();
        int columnCount = meta_data.getColumnCount();

        for (int index = 1; index <= columnCount; index++) {

          try {

            String column = JdbcUtils.lookupColumnName(meta_data, index);
            Object value = JdbcUtils.getResultSetValue(rs, index, getColumnClass(column));
            bw.setPropertyValue(column, value);

          } catch (TypeMismatchException | NotWritablePropertyException e) {
          }
        }

        return mappedObject;
      }

    private Class<?> getColumnClass(String colName) {
        Class<?> out = mappedFields.get(colName);
        if (out == null){
            out=getBeanPropertyClass(colName,this.mappedClass);
            if(out != null)
                mappedFields.put(colName,out);
        }
        return out;
    }

    private Class<?> getBeanPropertyClass(String propName, Class<?> clazz) {
        int sep=propName.lastIndexOf(PropertyAccessor.NESTED_PROPERTY_SEPARATOR_CHAR);
        if(sep>0){
            Class<?> superclass=getBeanPropertyClass(propName.substring(0, sep),clazz);
            return getBeanPropertyClass(propName.substring(sep+1),superclass);
        }else{  
            PropertyDescriptor pd = BeanUtils.getPropertyDescriptor(clazz, propName);
            if(pd!=null)
                return pd.getPropertyType();
        }
        return null;
    }
}