问题
需求:
来源于更新数据的一个接口,要求可以修改类中某一些字段的值,可以仅修改一部分,没有修改的字段默认为不修改。
例中使用了一个视图层的包装对象vo,包含了需要更新的目标底层实体po的一个扩展子类(假设这个对象就是poi),和一些其他的无关属性。从前端获取到已经改好数据的vo后,需要保存已经更新的po。
思路
使用BeanUtils.copyProperties(source, target, ignoreProperties)
这个方法,将源的属性,过滤掉一部分属性名,复制到目标上
ignoreProperties的声明类型是String… ignoreProperties
为获取一个能得到属性字段名的数组,需要用反射机制
过程
- 新建一个po对象,使用copyProperties复制poi已有值的属性到po里
- 设计一个方法获取不为空的字段名数组,供过滤功能的调用
- 再使用copyProperties的过滤重载方法,将原po复制到新po
反射获取字段名的实现
目标是获取不为空的字段
/**
* 用反射机制来得到vo中itemsCustom的不为空的属性
* @param objClass 为目标的Class对象,调用时为实体类的Class对象,并不是vo
* @param vo
* @return
* @throws ClassNotFoundException
*/
private String[] getProperties(Class objClass,ItemsQueryVo vo) throws ClassNotFoundException {
//得到ItemsCustom的class类
ItemsCustom obj = vo.getItemsCustom();
List<String> properties = new ArrayList<>();
//遍历字段
try {
//使用getDeclaredFields()方法而不是getFields()的原因是
//该方法明确的只需要匹配objClass类的字段,
//不使用obj.getClass()的原因也是如此,因为obj的类继承自objClass的类
for(Field field: objClass.getDeclaredFields()) {
//使其可以访问private
field.setAccessible(true);
//如果字段不为空
if(field.get(obj)!=null)
properties.add(field.getName());
}
}catch (Exception e) {
/*
* 如果获取出了错,return null的方法相当于
* 源的所有字段都是空的,目标在外部会被完全覆盖掉,这次更新相当于无效了
*/
return null;
}
//转数组
String[] propers = new String[properties.size()];
return properties.toArray(propers);
}
上段代码就实现了过程中的第二步
利用上述代码的简单方法可以写更多类似且更有通用性的工具