【问题标题】:Copy specific fields by using BeanUtils.copyProperties?使用 BeanUtils.copyProperties 复制特定字段?
【发布时间】:2011-07-02 01:20:44
【问题描述】:

springframework.beans.BeanUtils 对复制对象非常有用,我经常使用“ignoreProperties”选项。但是,有时我只想复制特定的对象(基本上,与“忽略属性”相反)。有谁知道我该怎么做?任何帮助将不胜感激。

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;
    }    
}

【问题讨论】:

    标签: java spring spring-mvc apache-commons


    【解决方案1】:

    看看这个:BeanPropertyCopyUtil

    例子:

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

    您还需要 Apache Commons BeanUtils。

    【讨论】:

    • 这不是实现此目的的适当方式。如果你的属性名被修改了怎么办?将其作为字符串传递并不是更好的方法,而是使用 Field[] fields = destination.getClass().getDeclaredFields(); 获取所有字段;并遍历 (Field field : fields){ //ur copy stuff here } 的字段
    • 这不适用于子属性,假设我想忽略所有名称为“id”的属性。
    【解决方案2】:

    如果您不想使用 Commons BeanUtils,您仍然可以通过 BeanWrapper 使用 Spring。

    您必须手动循环遍历所有属性,因此您需要创建一个静态辅助方法。

    您始终可以复制 copyProperties 正在执行的操作并根据自己的喜好进行调整: http://tinyurl.com/BeanUtils-copyProperties

    【讨论】:

      【解决方案3】:

      您可以使用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);
      }
      

      【讨论】:

      • BeanWrapper 技术快了 25%。 :)
      • Spring 建议改用PropertyAccessorFactory.forBeanPropertyAccess(Object)source
      • 如何获得 Iterable 属性?
      • @kiedysktos Iterable 是一个由 Collection 扩展的接口,所以这个方法会接受任何Collection&lt;String&gt;
      • 关于 BeanWrapper 的提示:使用 trgWrap.setAutoGrowNestedPaths(true) 来避免 NullValueInNestedPathException
      【解决方案4】:

      这是一个带有 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();
          }
      }
      

      【讨论】:

        【解决方案5】:

        您可以使用 org.springframework.beans.BeanUtils.copyProperties(Object source, Object target, Class editable) throws BeansException

        确保目标实现可编辑的接口,该接口定义了将被复制的属性。

        【讨论】:

          【解决方案6】:

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

          例如。

          String[] ignoreProperties= new String[]{"field1","field2"};
          
          BeanUtils.copyProperties(a, b,ignoreProperties);
          

          【讨论】:

            猜你喜欢
            • 2017-11-22
            • 2013-11-14
            • 1970-01-01
            • 2011-09-14
            • 2017-04-14
            • 2020-04-01
            • 1970-01-01
            • 2014-12-07
            • 1970-01-01
            相关资源
            最近更新 更多