关于BeanUtils拷贝null属性的问题
jen wang
帮同事查看物流发货问题时,发现BeanUtils在copy null属性时会有一些问题。现在总结一下现象、原因和解决方法。
问题现象
1.当源对象(a)中存在一个java.sql.Date类型的属性并且值为null,目标对象(b)中也存在这个同名同类型的属性。把a对象属性值copy给b时BeanUtils.copyProperties(b, a);会抛出异常;
2.当源对象(a)中存在一个java.sql.Date类型的属性并且值为null,目标对象(b)不存在这个同名同类型的属性,copy时没问题。
原因
查看BeanUtils源代码,定位到org.apache.commons.beanutils.BeanUtilsBean.copyProperties(Object
dest, Object orig)方法的关键代码,
public void copyProperties(Object dest, Object orig)
throws
IllegalAccessException, InvocationTargetException {
……
if (getPropertyUtils().isReadable(orig, name) &&
getPropertyUtils().isWriteable(dest,
name)) {
try {
Object value =
getPropertyUtils().getSimpleProperty(orig,
name);
copyProperty(dest,
name, value);
} catch (NoSuchMethodException e) {
; // Should not happen
}
}
……
}
isWriteable这一行,当目标对象没有相应的属性时不进行copy,所以不会有问题(现象2)。
再看copyProperty方法的关键代码,
引起现象1的代码为value =
converter.convert(type, value);这行,这里会抛出一个类型转换错误。转化器在转化时报错,需要找出这个转化器,继续往下看代码,ConvertUtilsBean.lookup(Class
clazz)方法,
再看converters中注册的转化器方法ConvertUtilsBean.deregister()的关键代码,
找到了相应的转化器SqlDateConverter,异常就在这个SqlDateConverter转化类型时抛出,当java.sql.Date类型的属性值为null时抛异常。
解决方法
<!--[if !supportLists]-->l <!--[endif]-->方法一
从convert方法可以看出只要想办法把useDefault和defaultValue设值就能解决,SqlDateConverter的另外一个构造方法可以设置这两个值,问题是从哪里把这个自己构造的converter 注册进去。从BeanUtils到BeanUtilsBean再到ConvertUtilsBean的找,发现都是写死的调用ConvertUtilsBean.deregister()方法注册的,最后发现ConvertUtilsBean有个register(Converter
converter, Class clazz)方法可以注册,而ConvertUtilsBean又是在BeanUtilsBean里new出来的,那么只要获取到这个ConvertUtilsBean即可,BeanUtilsBean提供了获取的方法。因此在BeanUtils.copyProperties(b,
a);加上下面这句代码即可
BeanUtilsBean.getInstance().getConvertUtils().register(new
SqlDateConverter(null),Date.class);
另外有一个辅助类也可以,
ConvertUtils.register(new
SqlDateConverter(null),Date.class);
<!--[if !supportLists]-->l <!--[endif]-->方法二
从上面copyProperty方法可以看出,只有找到注册过的转化器,才使用转化器进行对值的转化,否则直接copy value。而deregister中并没有对java.util.Date注册相应的转化器,所以把java.sql.Date改为java.util.Date也可以解决问题。
<!--[if !supportLists]-->l <!--[endif]-->方法三
把java.sql.Date的转化器去掉ConvertUtils.deregister(Date.class);
问题延伸
从上述分析可以看出,拷贝含有java.sql.Time,java.sql.Timestamp,java.io.File,java.net.URL等类型的null属性也会有类似的问题,使用时需要多加小心。
在字段属性比较明确并且较少的情况下,单单为了简化代码或者使代码优雅而引入BeanUtils这种相对复杂的copy机制是否值得,需要权衡,毕竟它增加了复杂性也牺牲了一些性能的。
- 大小: 39.1 KB
- 大小: 11.6 KB
- 大小: 39.4 KB
- 大小: 23.9 KB
分享到:
相关推荐
BeanUtils工具是一种方便我们对JavaBean进行操作的工具,是Apache组织下的产品。beanUtils 可以便于对javaBean的属性、对象进行赋值,beanUtils可以将一个MAP集合的数据拷贝到一个javabean对象中。
详见 http://blog.csdn.net/arttecme/article/details/8566818
BeanUtils工具由Apache软件基金组织编写,提供给我们使用,主要解决的问题是:把对象的属性数据封装到对象中。在整个J2EE的编程过程中,我们经常会从各种配置文件中读取相应的数据,需要明白的一点是从配置文件中...
BeanUtils 是 Apache commons组件的成员之一,主要用于简化JavaBean封装数据的操作。它可以给JavaBean封装一个字符串数据,也可以将一个表单提交的所有数据封装到JavaBean中。使用第三方工具,需要导入jar包:
BeanUtils最核心的好处在于:我们在编码时,并不需要知道我们处理的JavaBeans具体是什么类型,有哪些属性,这些信息是可以动态获取的,甚至我们都可以不必去关心事实... BeanUtils对这个问题提供了一种优雅的解决方案。
Beanutils基本用法.doc 。一些常用方法的介绍。
apache的beanutils包 自己用的不错 分享给大家。。。
对于JavaBean,简单的来说,就是要有一个空参的构造器和对属性的getXXX方法和setXXX方法。 在由JDK提供的默认的API中,有java.beans包,里面有诸如Introspector,BeanInfo,PropertyDescriptor等用来操作JavaBean的...
BeanUtils教程BeanUtils教程BeanUtils教程BeanUtils教程BeanUtils教程BeanUtils教程
BeanUtils_1.8.3最新帮助文档,希望对给位有用。。。
赠送jar包:commons-beanutils-1.9.4.jar; 赠送原API文档:commons-beanutils-1.9.4-javadoc.jar; 赠送源代码:commons-beanutils-1.9.4-sources.jar; 赠送Maven依赖信息文件:commons-beanutils-1.9.4.pom; ...
使用beanutils可轻松利用Java反射机制来完成所需功能,而不需要详细研究反射的原理和使用,同时beanutils类库中提出了动态Bean的概念,可在运行时动态对Bean中属性数据类型进行修改以及增删属性。
BeanUtils工具由Apache软件基金组织编写,提供给我们使用,主要解决的问题是:把对象的属性数据封装到对象中
commons-beanutils-1.8.0.jar beanutils.jar beanutils.jar工具包
BeanUtils用法
BeanUtils的包BeanUtils的包BeanUtils的包BeanUtils的包BeanUtils的包BeanUtils的包BeanUtils的包BeanUtils的包BeanUtils的包
赠送jar包:commons-beanutils-1.9.4.jar; 赠送原API文档:commons-beanutils-1.9.4-javadoc.jar; 赠送源代码:commons-beanutils-1.9.4-sources.jar; 赠送Maven依赖信息文件:commons-beanutils-1.9.4.pom; ...
Commons-beanutils jar包,比较新希望对大家能有帮助
BeanUtils.copyProperteis(dest,orgi); 属性拷贝
BeanUtils工具 .jar 包使用很简单 可以参考博客java学习笔记——javaweb之BeanUtils、EL、JSTL