前述:
日常开发中对bean操作,有很多小技巧:
复制一个实体类的属性:
使用spring的bean工具类:
//org.springframework.beans.BeanUtils包下:
BeanUtils.copyProperties(空实体类对象,目标实体类对象);
apache的公用工具类:
也有复制目标实体类的属性到另一个实体类的方法:
//org.apache.commons.beanutils包下
BeanUtils.copyProperties(目标实体类对象,空实体类对象);
相比之下:spring的工具类只能复制实体类的属性到目标对象中,而apache的目标实体类还可以是map或者动态bean,底层会对其进行判断类型,来解析获取属性,并赋值。
BeanMap:使bean对象和map绑定,保持一致
org.springframework.cglib.beans:BeanMap
Bean转map&map转bean:
import org.springframework.cglib.beans.BeanMap;
public static void main(String[] args) {
//创建bean对象
User user = new User();
//通过对象创建beanMap,使beanMap与user对象关联绑定
BeanMap beanMap = BeanMap.create(user);
//这样修改user,beanMap会随之改变
user.setName("名字");
log.info("对象转Map{}", beanMap);
//这样修改beanMap,user会随之改变
beanMap.put("age","11");
log.info("Map转对象{}", user);
}
本次出现问题的是我用的
apache的公用工具类org.apache.commons.beanutils包下:
将实体类对象转换成MAP:
Map<String,Object> map=BeanUtils.describe(实体类对象);
问题简述:
通过BeanUtils.describe(实体类对象);获取实体类的所有属性信息,并存到数据库中,但是这个实体类有日期格式,这个方法会将日期格式转换成字符串:Fri Aug 21 18:36:11 CST 2020这种格式,这样再将这个map作为参数传到dao层,执行sql就会报错:ORA-01858 数字格式的数据被非数字格式的数据填充。
但是我没有数字格式的字段,只有String和date类型的。通过debug才发现:
正常的时间字段应该转换成时间戳(毫秒数),这样的数字,所以才会报这个错误。因此使用工具类时,最好是查看其底层实现原理,确定是否有隐患。
解决方案比较简单:将时间格式转换好即可。
该方法底层源码:
原因分析
核心在ConverUtilsBean的convert方法,会将属性的值进行判断解析,如果是数组,则循环将每一个元素获取到再转换,如果不是数组,直接转换。
转换是通过Converter接口的实现类来完成,每种数据格式都有对应的数据转换类,比如日期的DateConverter.
但是他最后都通过这行代码转成了String。
converter = this.lookup(class$java$lang$String == null ? (class$java$lang$String = class$("java.lang.String")) : class$java$lang$String);
因此才会出现这个问题。
调用栈
convert:441, ConvertUtilsBean (org.apache.commons.beanutils)
getNestedProperty:716, BeanUtilsBean (org.apache.commons.beanutils)
getProperty:741, BeanUtilsBean (org.apache.commons.beanutils)
describe:514, BeanUtilsBean (org.apache.commons.beanutils)
describe:185, BeanUtils (org.apache.commons.beanutils)
核心方法
public String convert(Object value) {
if (value == null) {
return (String)null;
} else {
Converter converter;
if (value.getClass().isArray()) {
if (Array.getLength(value) < 1) {
return null;
} else {
value = Array.get(value, 0);
if (value == null) {
return (String)null;
} else {
converter = this.lookup(class$java$lang$String == null ? (class$java$lang$String = class$("java.lang.String")) : class$java$lang$String);
return (String)converter.convert(class$java$lang$String == null ? (class$java$lang$String = class$("java.lang.String")) : class$java$lang$String, value);
}
}
} else {
converter = this.lookup(class$java$lang$String == null ? (class$java$lang$String = class$("java.lang.String")) : class$java$lang$String);
return (String)converter.convert(class$java$lang$String == null ? (class$java$lang$String = class$("java.lang.String")) : class$java$lang$String, value);
}
}
}