sunfull 发表于 2017-12-24 12:23:29

org.springframework.beans.BeanUtils与org.apache.commons.beanutils.BeanUtils的copyP

知识点
  org.springframework.beans.BeanUtils与org.apache.commons.beanutils.BeanUtils都提供了copyProperties方法,作用是将一个Bean对象中的数据封装到另一个属性结构相似的Bean对象中
  1)两者的copyProperties方法参数位置不同
  org.springframework.beans.BeanUtils:  copyProperties(sourceDemo, targetDemo)
  org.apache.commons.beanutils.BeanUtils:  copyProperties(targetDemo, sourceDemo)
  2)要求两个Bean的属性名相同,且有对应的setXxx方法和getXxx方法。其实底层原理是使用sourceDemo的getXxx方法和targetDemo的setXxx方法
  3)sourceDemo有的属性而targetDemo没有的属性,不会封装到targetDemo对象中;
  targetDemo有的属性而sourceDemo没有的属性,会封装到targetDemo中,数据为默认值(注意基本类型默认值与引用类型默认值不同)
  4)类型转换问题
  a)基本类型与其对应的封装类型可以相互转换
  b)org.springframework.beans.BeanUtils与org.apache.commons.beanutils.BeanUtils对于String和Date类型转换的情况是不同的,具体看以下案例

案例一
  SourceDemo
  

package com.fortis.customer.test;  

  
import java.util.Date;
  

  
import org.apache.commons.lang3.builder.ToStringBuilder;
  

  

public>
  

private int>
  

private String name;  

  

private String address;  

  

private Date createTime;  

  

public int getId() {  

return>
}  

  

public void setId(int>
this.id =>
}  

  

public String getName() {  

return name;  
}
  

  

public void setName(String name) {  

this.name = name;  
}
  

  

public String getAddress() {  

return address;  
}
  

  

public void setAddress(String address) {  

this.address = address;  
}
  

  

public Date getCreateTime() {  

return createTime;  
}
  

  

public void setCreateTime(Date createTime) {  

this.createTime = createTime;  
}
  

  
@Override
  

public String toString() {  

return ToStringBuilder.reflectionToString(this);  
}
  

  
}
  

  TargetDemo
  

package com.fortis.customer.test;  

  
import java.util.Date;
  

  
import org.apache.commons.lang3.builder.ToStringBuilder;
  

  

public>
  

private Integer>
  

private String name;  

  

private String email;  

  

private Date createTime;  

  

public Integer getId() {  

return>
}  

  

public void setId(Integer>
this.id =>
}  

  

public String getName() {  

return name;  
}
  

  

public void setName(String name) {  

this.name = name;  
}
  

  

public String getEmail() {  

return email;  
}
  

  

public void setEmail(String email) {  

this.email = email;  
}
  

  

public Date getCreateTime() {  

return createTime;  
}
  

  

public void setCreateTime(Date createTime) {  

this.createTime = createTime;  
}
  

  
@Override
  

public String toString() {  

return ToStringBuilder.reflectionToString(this);  
}
  

  
}
  

  Test
  

package com.fortis.customer.test;  

  
import java.lang.reflect.InvocationTargetException;
  
import java.util.Date;
  

  

public>
  

public static void main(String[] args) throws IllegalAccessException, InvocationTargetException {  

  
SourceDemo sourceDemo
= new SourceDemo();  
sourceDemo.setId(
10);  
sourceDemo.setName(
"姓名");  
sourceDemo.setAddress(
"地址");  
sourceDemo.setCreateTime(
new Date());  

  
TargetDemo targetDemo
= new TargetDemo();  
org.springframework.beans.BeanUtils.copyProperties(sourceDemo, targetDemo);
  
System.
out.println(targetDemo);  

  
org.apache.commons.beanutils.BeanUtils.copyProperties(targetDemo, sourceDemo);
  
System.
out.println(targetDemo);  
}
  
}
  

  测试效果:
  

  
[id
=10,name=姓名,email=<null>,createTime=Fri Jun 30 16:19:31 CST 2017]  

  结论:基本类型与其对应的封装类型是可以相互转换的

案例二
  SourceDemo
  

package com.fortis.customer.test;  

  
import java.util.Date;
  

  
import org.apache.commons.lang3.builder.ToStringBuilder;
  

  

public>
  

private int>
  

private String name;  

  

private String address;  

  

private Date createTime;  

  

public int getId() {  

return>
}  

  

public void setId(int>
this.id =>
}  

  

public String getName() {  

return name;  
}
  

  

public void setName(String name) {  

this.name = name;  
}
  

  

public String getAddress() {  

return address;  
}
  

  

public void setAddress(String address) {  

this.address = address;  
}
  

  

public Date getCreateTime() {  

return createTime;  
}
  

  

public void setCreateTime(Date createTime) {  

this.createTime = createTime;  
}
  

  
@Override
  

public String toString() {  

return ToStringBuilder.reflectionToString(this);  
}
  

  
}
  

  TargetDemo
  

package com.fortis.customer.test;  

  
import org.apache.commons.lang3.builder.ToStringBuilder;
  

  

public>
  

private Integer>
  

private String name;  

  

private String email;  

  

private String createTime;  

  

public Integer getId() {  

return>
}  

  

public void setId(Integer>
this.id =>
}  

  

public String getName() {  

return name;  
}
  

  

public void setName(String name) {  

this.name = name;  
}
  

  

public String getEmail() {  

return email;  
}
  

  

public void setEmail(String email) {  

this.email = email;  
}
  

  

public String getCreateTime() {  

return createTime;  
}
  

  

public void setCreateTime(String createTime) {  

this.createTime = createTime;  
}
  

  
@Override
  

public String toString() {  

return ToStringBuilder.reflectionToString(this);  
}
  

  
}
  

  Test
  

package com.fortis.customer.test;  

  
import java.lang.reflect.InvocationTargetException;
  
import java.util.Date;
  

  

public>
  

public static void main(String[] args) throws IllegalAccessException, InvocationTargetException {  

  
SourceDemo sourceDemo
= new SourceDemo();  
sourceDemo.setId(
10);  
sourceDemo.setName(
"姓名");  
sourceDemo.setAddress(
"地址");  
sourceDemo.setCreateTime(
new Date(0));  

  
TargetDemo targetDemo
= new TargetDemo();  
org.springframework.beans.BeanUtils.copyProperties(sourceDemo, targetDemo);
  
System.
out.println(targetDemo);  

  

//org.apache.commons.beanutils.BeanUtils.copyProperties(targetDemo, sourceDemo);  

//System.out.println(targetDemo);  
    }
  
}
  

  测试效果:
  

Exception in thread "main" org.springframework.beans.FatalBeanException: Could not copy properties from source to target; nested exception is java.lang.IllegalArgumentException: argument type mismatch  
at org.springframework.beans.BeanUtils.copyProperties(BeanUtils.java:
599)  
at org.springframework.beans.BeanUtils.copyProperties(BeanUtils.java:
509)  
at com.fortis.customer.test.Test.main(Test.java:
17)  
Caused by: java.lang.IllegalArgumentException: argument type mismatch
  
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
  
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
  
at java.lang.reflect.Method.invoke(Unknown Source)
  
at org.springframework.beans.BeanUtils.copyProperties(BeanUtils.java:
596)  
...
2 more  

  结论:org.springframework.beans.BeanUtils.copyProperties不可以将java.util.Date类型转换成String类型
  同时:也不可将java.sql.Date类型转换成String类型(因为网上搜的说可以支持java.sql.Date类型,我自己测试了一下发现不可以,还是信自己靠谱)
  

Exception in thread "main" org.springframework.beans.FatalBeanException: Could not copy properties from source to target; nested exception is java.lang.IllegalArgumentException: argument type mismatch  
at org.springframework.beans.BeanUtils.copyProperties(BeanUtils.java:
599)  
at org.springframework.beans.BeanUtils.copyProperties(BeanUtils.java:
509)  
at com.fortis.customer.test.Test.main(Test.java:
17)  
Caused by: java.lang.IllegalArgumentException: argument type mismatch
  
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
  
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
  
at java.lang.reflect.Method.invoke(Unknown Source)
  
at org.springframework.beans.BeanUtils.copyProperties(BeanUtils.java:
596)  
...
2 more  


案例三
  Test
  

package com.fortis.customer.test;  

  
import java.lang.reflect.InvocationTargetException;
  
import java.util.Date;
  

  

public>
  

public static void main(String[] args) throws IllegalAccessException, InvocationTargetException {  

  
SourceDemo sourceDemo
= new SourceDemo();  
sourceDemo.setId(
10);  
sourceDemo.setName(
"姓名");  
sourceDemo.setAddress(
"地址");  
sourceDemo.setCreateTime(
new Date(0));  

  
TargetDemo targetDemo
= new TargetDemo();  

//org.springframework.beans.BeanUtils.copyProperties(sourceDemo, targetDemo);  

//System.out.println(targetDemo);  
      
  
org.apache.commons.beanutils.BeanUtils.copyProperties(targetDemo, sourceDemo);
  
System.out.println(targetDemo);
  
}
  
}
  

  注:SourceDemo和TargetDemo与案例二相同
  测试效果:java.util.Date
  

  

  结论:org.apache.commons.beanutils.BeanUtils.copyProperties可以将java.util.Date类型转换成String类型
  测试效果:java.sql.Date
  

  

  结论:org.apache.commons.beanutils.BeanUtils.copyProperties可以将java.sql.Date类型转换成String类型
  注意:虽然都可以转换,但发现两者的日期格式还是不同的

案例四:
  SourceDemo
  

package com.fortis.customer.test;  

  
import org.apache.commons.lang3.builder.ToStringBuilder;
  

  

public>
  

private int>
  

private String name;  

  

private String address;  

  

private String createTime;  

  

public int getId() {  

return>
}  

  

public void setId(int>
this.id =>
}  

  

public String getName() {  

return name;  
}
  

  

public void setName(String name) {  

this.name = name;  
}
  

  

public String getAddress() {  

return address;  
}
  

  

public void setAddress(String address) {  

this.address = address;  
}
  

  

public String getCreateTime() {  

return createTime;  
}
  

  

public void setCreateTime(String createTime) {  

this.createTime = createTime;  
}
  

  
@Override
  

public String toString() {  

return ToStringBuilder.reflectionToString(this);  
}
  

  
}
  

  TargetDemo
  

package com.fortis.customer.test;  

  
import java.util.Date;
  

  
import org.apache.commons.lang3.builder.ToStringBuilder;
  

  

public>
  

private Integer>
  

private String name;  

  

private String email;  

  

private Date createTime;  

  

public Integer getId() {  

return>
}  

  

public void setId(Integer>
this.id =>
}  

  

public String getName() {  

return name;  
}
  

  

public void setName(String name) {  

this.name = name;  
}
  

  

public String getEmail() {  

return email;  
}
  

  

public void setEmail(String email) {  

this.email = email;  
}
  

  

public Date getCreateTime() {  

return createTime;  
}
  

  

public void setCreateTime(Date createTime) {  

this.createTime = createTime;  
}
  

  
@Override
  

public String toString() {  

return ToStringBuilder.reflectionToString(this);  
}
  

  
}
  

  Test
  

package com.fortis.customer.test;  

  
import java.lang.reflect.InvocationTargetException;
  
import java.text.SimpleDateFormat;
  
import java.util.Date;
  

  

public>
  

public static void main(String[] args) throws IllegalAccessException, InvocationTargetException {  

  
SourceDemo sourceDemo
= new SourceDemo();  
sourceDemo.setId(
10);  
sourceDemo.setName(
"姓名");  
sourceDemo.setAddress(
"地址");  
sourceDemo.setCreateTime(
new SimpleDateFormat("yyyyMMddHHmmss").format(new Date(0)));  

  
TargetDemo targetDemo
= new TargetDemo();  

org.springframework.beans.BeanUtils.copyProperties(sourceDemo, targetDemo);  

System.out.println(targetDemo);  
      
  
//org.apache.commons.beanutils.BeanUtils.copyProperties(targetDemo, sourceDemo);
  
//System.out.println(targetDemo);
  
}
  
}
  

  测试效果:
  

Exception in thread "main" org.springframework.beans.FatalBeanException: Could not copy properties from source to target; nested exception is java.lang.IllegalArgumentException: argument type mismatch  
at org.springframework.beans.BeanUtils.copyProperties(BeanUtils.java:
599)  
at org.springframework.beans.BeanUtils.copyProperties(BeanUtils.java:
509)  
at com.fortis.customer.test.Test.main(Test.java:
18)  
Caused by: java.lang.IllegalArgumentException: argument type mismatch
  
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
  
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
  
at java.lang.reflect.Method.invoke(Unknown Source)
  
at org.springframework.beans.BeanUtils.copyProperties(BeanUtils.java:
596)  
...
2 more  

  结论:org.springframework.beans.BeanUtils.copyProperties不可以将String类型转换成java.util.Date类型
  同时:也不可将String类型转换成java.sql.Date类型

案例五
  Test
  

package com.fortis.customer.test;  

  
import java.lang.reflect.InvocationTargetException;
  
import java.text.SimpleDateFormat;
  
import java.util.Date;
  


  
public>  

  
public static void main(String[] args) throws IllegalAccessException, InvocationTargetException {
  

  
SourceDemo sourceDemo = new SourceDemo();
  
sourceDemo.setId(10);
  
sourceDemo.setName("姓名");
  
sourceDemo.setAddress("地址");
  
sourceDemo.setCreateTime(new SimpleDateFormat("yyyyMMddHHmmss").format(new Date(0)));
  

  
TargetDemo targetDemo = new TargetDemo();
  
//org.springframework.beans.BeanUtils.copyProperties(sourceDemo, targetDemo);
  
//System.out.println(targetDemo);
  
      
  
org.apache.commons.beanutils.BeanUtils.copyProperties(targetDemo, sourceDemo);
  
System.out.println(targetDemo);
  
}
  
}
  

  测试效果:java.util.Date
  

log4j:WARN No appenders could be found for logger (org.apache.commons.beanutils.converters.BooleanConverter).  
log4j:WARN Please initialize the log4j system properly.
  
Exception
in thread "main" org.apache.commons.beanutils.ConversionException: DateConverter does not support default String to 'Date' conversion.  
at org.apache.commons.beanutils.converters.DateTimeConverter.toDate(DateTimeConverter.java:
468)  
at org.apache.commons.beanutils.converters.DateTimeConverter.convertToType(DateTimeConverter.java:
343)  
at org.apache.commons.beanutils.converters.AbstractConverter.convert(AbstractConverter.java:
156)  
at org.apache.commons.beanutils.converters.ConverterFacade.convert(ConverterFacade.java:
60)  
at org.apache.commons.beanutils.BeanUtilsBean.convert(BeanUtilsBean.java:
1078)  
at org.apache.commons.beanutils.BeanUtilsBean.copyProperty(BeanUtilsBean.java:
437)  
at org.apache.commons.beanutils.BeanUtilsBean.copyProperties(BeanUtilsBean.java:
286)  
at org.apache.commons.beanutils.BeanUtils.copyProperties(BeanUtils.java:
137)  
at com.fortis.customer.test.Test.main(Test.java:
21)  

  结论:org.apache.commons.beanutils.BeanUtils
  看错误日志,发现说是默认的转换器是不可以将String类型转换成java.util.Date,可能自己配置一个转换器就可以转了吧,我没有测试过
  测试效果:java.sql.Date
  

log4j:WARN No appenders could be found for logger (org.apache.commons.beanutils.converters.BooleanConverter).  
log4j:WARN Please initialize the log4j system properly.
  
Exception
in thread "main" org.apache.commons.beanutils.ConversionException: String must be in JDBC format to create a java.sql.Date  
at org.apache.commons.beanutils.converters.DateTimeConverter.toDate(DateTimeConverter.java:
436)  
at org.apache.commons.beanutils.converters.DateTimeConverter.convertToType(DateTimeConverter.java:
343)  
at org.apache.commons.beanutils.converters.AbstractConverter.convert(AbstractConverter.java:
156)  
at org.apache.commons.beanutils.converters.ConverterFacade.convert(ConverterFacade.java:
60)  
at org.apache.commons.beanutils.BeanUtilsBean.convert(BeanUtilsBean.java:
1078)  
at org.apache.commons.beanutils.BeanUtilsBean.copyProperty(BeanUtilsBean.java:
437)  
at org.apache.commons.beanutils.BeanUtilsBean.copyProperties(BeanUtilsBean.java:
286)  
at org.apache.commons.beanutils.BeanUtils.copyProperties(BeanUtils.java:
137)  
at com.fortis.customer.test.Test.main(Test.java:
21)  

  结论:org.apache.commons.beanutils.BeanUtils
  看错误日志,发现说是需要将String类型转成java.sql.Date,使用simpleDateFormat是将String类型转成java.util.Date,可能转成java.sql.Date就可以了吧,我没测试过
  注意:我这里说的转换,单纯是指这一行代码sourceDemo.setCreateTime(new SimpleDateFormat("yyyyMMddHHmmss").format(new Date(0)));而不是两个Bean的类型转换
  总之,无论是org.springframework.beans.BeanUtils还是org.apache.commons.beanutils.BeanUtils,默认情况下都不能将String类型转成Date类型
  案例六:
  SourceDemo:
  private String name;
  TargetDemo:
  private String name = “马超”;
  private String email = "张飞";
  复制之后的结果:name = null,email = “张飞”
  SourceDemo:
  private String name = “诸葛亮”;
  TargetDemo:
  private String name = “马超”;
  private String email = "张飞";
  复制之后的结果:name = “诸葛亮”,email = “张飞”
  注:使用两种BeanUtils效果相同
页: [1]
查看完整版本: org.springframework.beans.BeanUtils与org.apache.commons.beanutils.BeanUtils的copyP