spring BeanUtils.copyProperties只拷贝不为null的属性

本文详细介绍了如何在使用Spring框架时,通过重写BeanUtils.copyProperties方法来解决数据绑定过程中对null值的不当处理问题,特别针对修改操作场景进行了优化。

 

在MVC的开发模式中经常需要将model与pojo的数据绑定,apache和spring的工具包中都有BeanUtils,使用其中的copyProperties方法可以非常方便的进行这些工作,但在实际应用中发现,对于null的处理不太符合个人的需要,例如在进行修改操作中只需要对model中某一项进行修改,那么一般我们在页面上只提交model的ID及需要修改项的值,这个时候使用BeanUtils.copyProperties会将其他的null绑定到pojo中去。为解决这个问题我重写了部分spring BeanUtils的代码如下

 

spring: 3.2.12,其他几个copyProperties方法最终都是调用的这个,

spring的比apache的的多一个带ignoreProperties的

private static void copyProperties(Object source, Object target, Class<?> editable, String... ignoreProperties)
		throws BeansException {

	Assert.notNull(source, "Source must not be null");
	Assert.notNull(target, "Target must not be null");

	Class<?> actualEditable = target.getClass();
	if (editable != null) {
		if (!editable.isInstance(target)) {
			throw new IllegalArgumentException("Target class [" + target.getClass().getName() +
					"] not assignable to Editable class [" + editable.getName() + "]");
		}
		actualEditable = editable;
	}
	PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable);
	List<String> ignoreList = (ignoreProperties != null) ? Arrays.asList(ignoreProperties) : null;

	for (PropertyDescriptor targetPd : targetPds) {
		Method writeMethod = targetPd.getWriteMethod();
		if (writeMethod != null && (ignoreProperties == null || (!ignoreList.contains(targetPd.getName())))) {
			PropertyDescriptor sourcePd = getPropertyDescriptor(source.getClass(), targetPd.getName());
			if (sourcePd != null) {
				Method readMethod = sourcePd.getReadMethod();
				if (readMethod != null &&
						ClassUtils.isAssignable(writeMethod.getParameterTypes()[0], readMethod.getReturnType())) {
					try {
						if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
							readMethod.setAccessible(true);
						}
						Object value = readMethod.invoke(source);
						if(value != null){	//只拷贝不为null的属性 by zhao
							if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {
								writeMethod.setAccessible(true);
							}
							writeMethod.invoke(target, value);
						}
					}
					catch (Throwable ex) {
						throw new FatalBeanException(
								"Could not copy property '" + targetPd.getName() + "' from source to target", ex);
					}
				}
			}
		}
	}
}

 关键代码就是加一个判断

                        if(value != null){  //只拷贝不为null的属性 by zhao   
                            if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {   
                                writeMethod.setAccessible(true);   
                            }   
                            writeMethod.invoke(target, value);   
                        }

 

参考:http://simen-net.iteye.com/blog/644801

在使用 `BeanUtils.copyProperties` 时,若要实现属性值为空则不进行复制,可借助自定义方法 `getNullPropertyNames` 来获取源对象中所有值为 `null` 的属性名数组,然后将该数组作为第三个参数传递给 `BeanUtils.copyProperties` 方法。以下为示例代码: ```java import org.springframework.beans.BeanWrapper; import org.springframework.beans.BeanWrapperImpl; import java.beans.PropertyDescriptor; import java.util.HashSet; import java.util.Set; import org.springframework.beans.BeanUtils; public class PublicUtils { /** * 获取所有字段为null属性名 * 用于BeanUtils.copyProperties()拷贝属性时,忽略空值 * @param source * @return */ public static String[] getNullPropertyNames (Object source) { final BeanWrapper src = new BeanWrapperImpl(source); java.beans.PropertyDescriptor[] pds = src.getPropertyDescriptors(); Set<String> emptyNames = new HashSet<String>(); for(java.beans.PropertyDescriptor pd : pds) { Object srcValue = src.getPropertyValue(pd.getName()); if (srcValue == null) emptyNames.add(pd.getName()); } String[] result = new String[emptyNames.size()]; return emptyNames.toArray(result); } public static void main(String[] args) { // 假设source和target是两个自定义对象 Object source = new Object(); Object target = new Object(); // 调用copyProperties方法,忽略空值 BeanUtils.copyProperties(source, target, PublicUtils.getNullPropertyNames(source)); } } ``` 在上述代码里,`getNullPropertyNames` 方法会遍历源对象的所有属性,把值为 `null` 的属性名存于一个 `Set` 集合,接着将集合转换为字符串数组并返回。在调用 `BeanUtils.copyProperties` 方法时,把源对象、目标对象以及 `getNullPropertyNames` 方法返回的数组当作参数传入,这样就能达成属性值为空时不进行复制的目的 [^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值