转载自http://jen.iteye.com/blog/1032521
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)
throwsIllegalAccessException, 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时抛异常。
解决方法
方法一
从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);
方法一个人最建议。
方法二
从上面copyProperty方法可以看出,只有找到注册过的转化器,才使用转化器进行对值的转化,否则直接copy value。而deregister中并没有对java.util.Date注册相应的转化器,所以把java.sql.Date改为java.util.Date也可以解决问题。
方法三
把java.sql.Date的转化器去掉ConvertUtils.deregister(Date.class);
问题延伸
从上述分析可以看出,拷贝含有java.sql.Time,java.sql.Timestamp,java.io.File,java.net.URL等类型的null属性也会有类似的问题,使用时需要多加小心。
在字段属性比较明确并且较少的情况下,单单为了简化代码或者使代码优雅而引入BeanUtils这种相对复杂的copy机制是否值得,需要权衡,毕竟它增加了复杂性也牺牲了一些性能的。
分享到:
相关推荐
5. **拷贝属性**:`BeanUtils.copyProperties()`方法可以实现对象间的属性深度拷贝,这对于创建对象副本或者在不同对象间传递数据十分便利。 6. **避免空指针异常**:BeanUtils库在处理null值时会进行保护,避免因...
BeanUtils的核心功能在于属性的自动类型转换和封装,它能够自动处理JavaBeans对象之间的属性拷贝,即使源对象和目标对象的属性类型不完全匹配,BeanUtils也能尝试进行类型转换。例如,将字符串转换为整型或浮点型,...
4. **空值处理**:对于null值的属性,BeanUtils提供了一种机制来处理,可以设定默认值或者忽略空值。 5. **国际化支持**:BeanUtils也与Apache Commons Locale和ResourceBundle结合,支持多语言环境下的Bean属性...
3. **避免空指针异常**:在处理可能为空的对象或属性时,BeanUtils工具包会进行检查,如果源对象或属性为null,它不会抛出NullPointerException,而是安全地跳过,这在处理不确定的数据源时非常有用。 4. **处理...
BeanUtils提供的API使得我们无需直接调用这些方法,而是通过字符串形式的属性名来操作Bean的属性。 1. **属性复制(Property Copying)** BeanUtils的最显著特性是`copyProperties()`方法,它允许我们从一个对象的...
- **数据转换**:在数据交换或序列化过程中,BeanUtils的属性拷贝功能能帮助快速地转换数据结构。 - **框架集成**:许多Java框架如Struts、Spring等,都可能依赖`commons-beanutils`来简化对象操作。 5. **注意...
例如,在公司内部,我们曾经遇到过使用commons包的BeanUtils进行属性拷贝时性能较差的情况。后来,我们换成了Spring的BeanUtils,性能好了很多。 其次,让我们来看一下BeanUtils的风险。使用BeanUtils进行属性拷贝...
虽然BeanUtils大大提高了开发效率,但它的无条件属性复制可能导致安全问题,比如当源对象包含敏感属性时,可能会被无意间复制。因此,在使用`copyProperties()`时,需谨慎处理源对象的属性。 7. **总结** Apache ...
虽然BeanUtils提供了极大的便利,但需要注意的是,它的属性拷贝功能可能会引发安全问题,例如在处理用户输入时未经验证就直接复制,可能会导致注入攻击。因此,使用时应确保对输入数据进行充分的校验和过滤。 六、...
然而,需要注意的是,尽管BeanUtils库提供了便利,但它的无条件属性复制可能会带来安全问题,如潜在的空指针异常或者属性覆盖。因此,在使用时,开发者应确保对目标对象进行适当的初始化,并了解属性复制的潜在风险...
BeanUtils在处理null值时有特别的处理方式,如果试图设置的属性不存在或者值为null,它不会抛出NullPointerException。这在处理不确定的数据源时非常有用,增强了代码的健壮性。 4. 格式转换: BeanUtils内部使用了...
3. **对象拷贝**:在对象模型转换时,BeanUtils的`copyProperties()`方法可以实现深度复制,避免了手动编写大量的赋值代码。 4. **属性操作**:对于拥有大量属性的复杂Bean对象,BeanUtils可以提供一种统一且简便的...
3. **空值处理**:BeanUtils还提供了处理null值的方法,如NullAwarePropertyUtils.copyProperties(),它可以避免因源对象中属性为null而导致的目标对象抛出NullPointerException。 4. **动态属性访问**:BeanUtils...
BeanUtils的核心功能是属性的复制,它通过反射机制来实现对象之间属性值的拷贝。例如,当我们从数据库查询结果中得到一个结果集,通常会将这些结果映射到Java Bean对象上,BeanUtils可以帮助我们自动填充Bean对象的...
Apache Commons BeanUtils是Java开发中的一个实用工具库,它提供了对JavaBeans属性操作的强大功能,极大地简化了开发者在处理对象属性时的代码。这个压缩包"Commons-beanutils.rar"包含了从1.4到1.9的不同版本,这...
Spring的BeanUtils组件为我们提供了简化属性复制的方法,比如`copyProperties`,它可以高效地将一个源对象的属性值拷贝到目标对象中去。这个过程是自动化完成的,开发者无需手动编写set方法来逐个赋值。 从给出的...
BeanUtil框架是一个在Java开发中常用的工具库,主要用于对象属性的获取、设置、拷贝以及类型转换等操作。它的设计目标是简化Java Bean的操作,提高代码的可读性和可维护性。这个“BeanUtil框架完整包”包含了...
使用这个工具类时,假设我们有两个POJO类`UserSource`和`UserTarget`,只需要调用`BeanUtils.copyProperties(sourceUser, targetUser)`即可完成值拷贝。 虽然反射提供了一种灵活的解决方案,但需要注意其性能开销。...
3. **属性复制**:BeanUtils.copyProperties()方法可以实现两个JavaBean之间属性的深拷贝或浅拷贝,大大简化了对象间的属性迁移。 4. **集合操作**:支持集合属性的处理,例如将一个数组或列表的值分配给JavaBean的...
Apache BeanUtils提供了便捷的属性拷贝功能,但在大规模或高性能应用中,其效率相对较低。相比其他如Spring的BeanUtils、Cglib的BeanCopier等工具,BeanUtils在处理大量对象复制时可能会导致性能瓶颈。这是因为...