通过使用BeanUtils.copyProperties复制特定字段?

42

springframework.beans.BeanUtils非常有用,可以复制对象,并且我经常使用“ignoreProperties”选项。但是,有时我只想复制特定的对象(基本上是“ignore Properties”的相反)。有人知道如何做到这一点吗?任何帮助将不胜感激。

import org.springframework.beans.BeanUtils;

public class Sample {    
    public static void main(String[] args) {    
        DemoADto demoADto = new DemoADto();
        demoADto.setName("Name of Demo A");
        demoADto.setAddress("Address of Demo A");

        DemoBDto demoBDto = new DemoBDto();

        // This is "ignoreProperties" option
        // But I want to know how I can copy only name field by using BeanUtils or something.
        BeanUtils.copyProperties(demoADto, demoBDto, new String[] {"address"});

        System.out.println(demoBDto.getName());
        System.out.println(demoBDto.getAddress());    
    }    
}

public class DemoADto {    
    private String name;    
    private String address;

    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 class DemoBDto {    
    private String name;    
    private String address;

    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;
    }    
}
6个回答

65
你可以使用BeanWrapper技术。这里是一个示例实现:
public static void copyProperties(Object src, Object trg, Iterable<String> props) {

    BeanWrapper srcWrap = PropertyAccessorFactory.forBeanPropertyAccess(src);
    BeanWrapper trgWrap = PropertyAccessorFactory.forBeanPropertyAccess(trg);

    props.forEach(p -> trgWrap.setPropertyValue(p, srcWrap.getPropertyValue(p)));

}

或者,如果你真的,真的想使用 BeanUtils,这里有一个解决方案。反转逻辑,通过比较完整的属性列表与包含项来收集排除项:

public static void copyProperties2(Object src, Object trg, Set<String> props) {
    String[] excludedProperties = 
            Arrays.stream(BeanUtils.getPropertyDescriptors(src.getClass()))
                  .map(PropertyDescriptor::getName)
                  .filter(name -> !props.contains(name))
                  .toArray(String[]::new);

    BeanUtils.copyProperties(src, trg, excludedProperties);
}

7
BeanWrapper技术提升了25%的速度。 :) - arnabkaycee
Springوژ¨èچگن½؟用PropertyAccessorFactory.forBeanPropertyAccess(Object)ن»£و›؟م€‚و‌¥و؛گ - bheussler
1
你如何获取 Iterable<String> 属性? - kiedysktos
@kiedysktos Iterable是由Collection扩展的接口,因此这个方法将接受任何Collection<String> - Sean Patrick Floyd
BeanWrapper的技巧:使用trgWrap.setAutoGrowNestedPaths(true)以避免NullValueInNestedPathException。 - gibaholms

3
如果您不想使用Commons BeanUtils,仍然可以使用Spring,方法是使用BeanWrapper
您需要手动循环遍历所有属性,因此最好编写一个静态的帮助方法。
您始终可以复制copyProperties正在执行的操作并进行调整: http://tinyurl.com/BeanUtils-copyProperties

2

看一下这个链接:BeanPropertyCopyUtil.

示例:

copyProperties(user, systemUser, "first firstName", "last lastName");

您还需要安装Apache Commons BeanUtils。

这不是实现这个的合适方式。如果您的属性名称被修改了怎么办?将其作为字符串传递并不是更好的方法,而是使用 Field[] fields = destination.getClass().getDeclaredFields(); 获取所有字段,然后遍历字段,例如:for (Field field : fields){ //在这里进行复制操作 } - Sadanand
这在子属性中不起作用,假设我想忽略所有名称为“id”的属性。 - Yogesh Prajapati

2

beanUtils有一个重载方法,我们可以传递一个要忽略的字段数组。

例如:

String[] ignoreProperties= new String[]{"field1","field2"};

BeanUtils.copyProperties(a, b,ignoreProperties);

enter image description here


1
你可以使用org.springframework.beans.BeanUtils.copyProperties(Object source, Object target, Class editable)方法,它会把source对象的属性复制到target对象中。需要注意的是,target对象需要实现editable接口,该接口定义了哪些属性会被复制。

0
这是一个与Spring BeanUtils类相关的示例:
public static void copyList(List sourceList,
        List targetList, Class targetType) {

    try {

        for (Object source : sourceList) {
            Object target = null;
            target = targetType.newInstance();
            BeanUtils.copyProperties(source, target);
            targetList.add(target);
        }

    } catch (InstantiationException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接