res:bean属性复制避免null值覆盖版本

前言

  • 最近在设计通用的 Service 和 Controller 层
  • 设计过程中涉及到实体对象(JPA)的更新操作
  • 原因1:JPA 的 saveAndFlush 方法会将把 null 也更新上去
  • 原因2:spring 的 BeanUtils.copyBeanProperties 方法会把 src 所有属性值包括 null 覆盖到 dest,不符合要求
  • 所以,利用反射,写一个属性复制方法代替 spring 的工具方法
  • 另外,controller 层使用 @ModelAttribut 也可以解决这个问题,这就是另一个主题

代码 copyBeanPropertiesIgoreNull

/**
 * 对象属性值拷贝,null 值覆盖修复版
 * @param beanSrc
 * @param beanDest
 */
public static void copyBeanPropertiesIgoreNull(Object beanSrc, Object beanDest){
	Class<?> clazzSrc = beanSrc.getClass();
	Class<?> clazzDest = beanDest.getClass();
	//获取所有属性,包括私有的和继承的
	List<Field> allFields = getAllFields(beanSrc);
	try {
	for(Field field:allFields) {
		String fieldName = field.getName(); //属性名
		if("serialVersionUID".equals(fieldName)) {
			continue;
		}
		PropertyDescriptor pd1 = getPropertyDescriptor(fieldName, clazzSrc);
		if(pd1!=null) {
			Method rMethod = pd1.getReadMethod();
			if(rMethod!=null) {
				Object fieldValue = rMethod.invoke(beanSrc); //属性值,引用类型,所以一般实体的属性用 Integer instead of int
				if(fieldValue!=null) { //关键:属性值为 null 就不要覆盖了
					PropertyDescriptor pd2 = getPropertyDescriptor(fieldName, clazzDest);
					if(pd2!=null) {
						Method wMethod = pd2.getWriteMethod();
						if(wMethod!=null) {
								wMethod.invoke(beanDest, fieldValue);
						}
					}
				}
			}
		}
	}
	} catch (IllegalAccessException | InvocationTargetException e) {
		e.printStackTrace();
		throw new RuntimeException(">> copyPropertiesIgoreNull exception", e);
	}
}
posted @ 2019-10-30 19:05  summaster  阅读(370)  评论(0编辑  收藏  举报