【问题标题】:BeanUtils copyProperties API to ignore null and specific propertieBeanUtils copyProperties API 忽略 null 和特定属性
【发布时间】:2013-06-29 08:01:07
【问题描述】:

Spring 的 BeanUtils.copyProperties() 提供了在复制 bean 时忽略特定属性的选项:

public static void copyProperties(Object source,
                 Object target,
                 String[] ignoreProperties) throws BeansException

Apache Commons BeanUtils 是否提供类似的功能?

在使用 Spring 的 BeanUtils.copyProperties() 时也可以忽略空值,我在 Commons BeanUtils 中看到了这个功能:

Date defaultValue = null;
DateConverter converter = new DateConverter(defaultValue);
ConvertUtils.register(converter, Date.class);

我可以用 Spring 的 BeanUtils 实现同样的效果吗?

【问题讨论】:

    标签: java spring mapping apache-commons-beanutils


    【解决方案1】:

    如果您使用org.springframework.beans.BeanUtils,您可以使用copyProperties(Object source, Object target, String... ignoreProperties) 方法忽略特定属性。一个例子,

    BeanUtils.copyProperties(sourceObj, targetObj, "aProperty", "another");
    

    【讨论】:

    • 这不适用于子属性,假设我想忽略所有名称为“id”的属性。
    • 问题不在于忽略子属性。如果没有关于忽略子属性的问题,请尝试创建一个新问题。
    【解决方案2】:

    如果您想忽略null-value,您必须在复制属性之前使用以下代码行:

    BeanUtilsBean.getInstance().getConvertUtils().register(false, false, 0);
    

    【讨论】:

    • sn-p 是做什么的?
    • 看来ConverterUtils不支持这种注册方式(至少1.7.0版本)
    • 不......它不起作用,这个答案缺乏解释。
    • 试过了,还是不行。第二个标志应该这样做,但它不起作用
    • 方法 .register(false, false, 0) 不存在
    【解决方案3】:

    这是一个示例代码 sn-p,我用于在复制到目标时跳过空字段。您可以使用属性名称、值等添加对特定属性的检查。我使用过 org.springframework.beans.BeanUtils

    public static void copyNonNullProperties(Object src, Object target) {
        BeanUtils.copyProperties(src, target, getNullPropertyNames(src));
    }
    
    public static String[] getNullPropertyNames(Object source) {
        final BeanWrapper src = new BeanWrapperImpl(source);
        PropertyDescriptor[] pds = src.getPropertyDescriptors();
    
        Set<String> emptyNames = new HashSet<String>();
        for (PropertyDescriptor pd : pds) {
            Object srcValue = src.getPropertyValue(pd.getName());
            if (srcValue == null)
                emptyNames.add(pd.getName());
        }
        String[] result = new String[emptyNames.size()];
        return emptyNames.toArray(result);
    }
    

    【讨论】:

      【解决方案4】:

      为了补充 Prajith 的答案,这是我选择源中存在空值的属性名称的一种方法。

      出于某种原因,我觉得这更具可读性。 您可以选择用 try-catch 包围或在方法级别添加 throws。

      public static void copyNonNullProperties(Object src, Object target) {
          BeanUtils.copyProperties(src, target, getNullPropertyNames(src));
      }
      
      public static String[] getNullPropertyNames(Object source) {
              List<String> nullValuePropertyNames = new ArrayList<>();
              for (Field f : source.getClass().getDeclaredFields()) {
                  try {
                      if (f.get(source) == null) {
                          nullValuePropertyNames.add(f.getName());
                      }
                  } catch (IllegalAccessException e) {
                      e.printStackTrace();
                  }
              }
              return nullValuePropertyNames.toArray(new String[0]);
          }
      

      【讨论】:

        【解决方案5】:

        忽略空值:

        BeanUtilsBean.getInstance().getConvertUtils().register(false, false, 0);
        

        忽略特定属性:

        public static void copyProperties(Object source,
                                      Object target,
                                      String... ignoreProperties)
                               throws BeansException
        

        忽略属性的文档:Spring 4.1.0 docs

        【讨论】:

          【解决方案6】:

          我已经用 BeansUtils 解决了这个问题,它也适用于嵌套类。

          class NullAwareBeanUtilsBean extends BeanUtilsBean {
              
              
              @Override
              public void copyProperty(Object dest, String name, Object value)
                      throws IllegalAccessException, InvocationTargetException {
                  if (value == null)
                      return;
                  else if(value instanceof NonNullCopy) {
                      Class<?> destClazz = value.getClass();
                          Class<?> origClazz = dest.getClass();
                          String className = destClazz.getSimpleName();
                  
                          for(Method m : origClazz.getDeclaredMethods()) {
                              if(m.getReturnType().equals(destClazz)) {
                                  copyProperties(m.invoke(dest, Collections.EMPTY_LIST.toArray()),value);
                              }                       
                          }
                          return;
                  }
          
                  super.copyProperty(dest, name, value);
              }
          
                 
          }
          
          
          

          我在此处发布的解决方案的完整说明:

          Copy non-null properties from one object to another using BeanUtils or similar

          【讨论】:

            【解决方案7】:

            如果您想忽略特定属性,请执行以下操作(来自 BeanUtils API)

            public static void copyProperties(Object source,
                                              Object target,
                                              String... ignoreProperties)
                                       throws BeansException
            

            下面的例子: 如果您想忽略名为“foo”的单个属性,只需添加为第三个参数

            BeanUtils.copyProperties(src, target,"foo");
            

            如果你想忽略一堆属性,创建一个列表并将其作为第三个参数值发送

            final List<String> exclusionsList = new ArrayList<>();
                    exclusionsList.add("foo");
                    exclusionsList.add("bar");
            BeanUtils.copyProperties(src, target,exclusionsList);   
            

            【讨论】:

              猜你喜欢
              • 2013-11-13
              • 2013-10-19
              • 2020-06-11
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-04-06
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多