原始类型的反射映射
Reflection mapping with primitive types
我需要一个用于 JDBC 的可嵌套 bean rowmapper,我使用了:
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 中有一个布尔值(原始)而不是布尔值(class)属性,它会失败。我怎样才能更正它让它映射原始类型 属性?
我认为您可以查看源代码 org.springframework.jdbc.core.BeanPropertyRowMapper
,您需要从 java class 定义中获取 class 类型,而不是从结果集元数据中获取。
例如,将您的 Class.forName(meta_data.getColumnClassName(index) 替换为以下方法 getClass(column)
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
那样做 cache/try catch
这可以是安迪解决方案的缓存版本,具有固定的嵌套 属性 查找。
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;
}
}
我需要一个用于 JDBC 的可嵌套 bean rowmapper,我使用了:
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 中有一个布尔值(原始)而不是布尔值(class)属性,它会失败。我怎样才能更正它让它映射原始类型 属性?
我认为您可以查看源代码 org.springframework.jdbc.core.BeanPropertyRowMapper
,您需要从 java class 定义中获取 class 类型,而不是从结果集元数据中获取。
例如,将您的 Class.forName(meta_data.getColumnClassName(index) 替换为以下方法 getClass(column)
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
那样做 cache/try catch这可以是安迪解决方案的缓存版本,具有固定的嵌套 属性 查找。
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;
}
}