Java 具有基元类型的反射映射
我需要一个用于JDBC的可嵌套bean行映射器,我使用了: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
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;
}
}