Java 具有基元类型的反射映射

Java 具有基元类型的反射映射,java,jdbc,reflection,mapping,Java,Jdbc,Reflection,Mapping,我需要一个用于JDBC的可嵌套bean行映射器,我使用了: public class NestedRowMapper<T> implements RowMapper<T> { private static Logger log = LoggerFactory.getLogger(NestedRowMapper.class); private Class<T> mappedClass; public NestedRowMap

我需要一个用于JDBC的可嵌套bean行映射器,我使用了:

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;
      }
    }
公共类NestedRowMapper实现行映射器{
私有静态记录器log=LoggerFactory.getLogger(NestedRowMapper.class);
私有类mappedClass;
公共NestedRowMapper(类mappedClass){
this.mappedClass=mappedClass;
}
@凌驾
public T mapRow(ResultSet rs,int rowNum)抛出SQLException{
T mappedObject=BeanUtils.instantiate(this.mappedClass);
BeanRapper bw=PropertyAccessorFactory.forBeanPropertyAccess(mappedObject);
bw.setAutologownestedPath(真);
ResultSetMetaData meta_data=rs.getMetaData();
int columnCount=meta_data.getColumnCount();

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

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

私有类getClass(字符串列){
PropertyDescriptor[]pds=BeanUtils.getPropertyDescriptors(this.mappedClass);
对于(PropertyDescriptor pd:pds){
if(pd.getName().equals(列)){
返回pd.getPropertyType();
}
}
返回null;
}

这只是一个示例,您需要像BeanPropertyRowMapper一样进行缓存/尝试捕获

这可以是一个带有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;
    }
}
公共类NestedRowMapper实现行映射器{
私有类mappedClass;
私人地图>();
公共NestedRowMapper(类mappedClass){
this.mappedClass=mappedClass;
}
@凌驾
public T mapRow(ResultSet rs,int rowNum)抛出SQLException{
T mappedObject=BeanUtils.instantiate(this.mappedClass);
BeanRapper bw=PropertyAccessorFactory.forBeanPropertyAccess(mappedObject);
bw.setAutologownestedPath(真);
ResultSetMetaData meta_data=rs.getMetaData();
int columnCount=meta_data.getColumnCount();
for(int index=1;index out=mappedFields.get(colName);
if(out==null){
out=getBeanPropertyClass(colName,this.mappedClass);
if(out!=null)
mappedFields.put(colName,out);
}
返回;
}
私有类getBeanPropertyClass(字符串propName,类clazz){
int sep=propName.lastIndexOf(PropertyAccessor.NESTED\u PROPERTY\u SEPARATOR\u CHAR);
如果(九月>0){
类超类=getBeanPropertyClass(propName.substring(0,sep),clazz);
返回getBeanPropertyClass(propName.substring(sep+1),超类);
}否则{
PropertyDescriptor pd=BeanUtils.getPropertyDescriptor(clazz,propName);
如果(pd!=null)
返回pd.getPropertyType();
}
返回null;
}
}

我有一个测试,它可以工作很长时间。您可以打印详细的失败日志吗?对于布尔值,我认为它在数据库中很小。我得到了一个静态值“选择1”查询,但它没有映射到我不久前编写的小库。我想它可能正在执行您需要的操作。@Tobia如果您在SQL中写入select 1,rs.getMetaData()如何执行此操作可以知道它应该是布尔类、int或long吗?jdbc将其设置为long,但我的bean有一个布尔属性。我不能将其更改为long,因为它对于所有其他查询来说都是布尔属性(tinyint(1))但是在这个查询中,我需要一个静态的1值。你认为缓存字段类足够吗?请看我的答案。我认为你可以在NestedRowMapper构造函数中进行所有列缓存,然后BeanUtils.getPropertyDescriptors也只调用一次,我的解决方案不调用getPropertyDescriptors()一次?我不想解析所有列,因为可能我只对少数字段使用了一个大Bean。对于每个列,您必须调用BeanUtils.getPropertyDescriptors(this.mappedClass)一次。我检查了它的代码,似乎它使用了缓存。所以多次调用我都没有问题think@andy在您的解决方案getClass(“父子”)返回的总是null。我修复了您的解决方案并添加了bean属性缓存。我使用getPropertyDescriptor(single)更改了getPropertyDescriptor(多个),因为我知道属性名称。谢谢!
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;
    }
}