【问题标题】:reflection copy non null properties from one object to another BeanUtils反射将非空属性从一个对象复制到另一个 BeanUtils
【发布时间】:2014-06-23 16:43:59
【问题描述】:

有这个:

public class Parent {
    private String name;
    private int age;
    private Date birthDate;
    private Work work;
    static class Work{
        private int years;
        private String employer;
    }

// getters and setters   
    public static void main(String[] args) {
        Parent c = new Parent;
        c.setAge(55)
        Work work=new Parent.Work();
        work.setEmployer("Example");
        c.setWork(work);
        //save c in a DB...
    }
}

我只想使用反射复制非空 属性。使用 beanUtils 的方法 described here 效果很好,但它复制了所有非空包装对象,而不仅仅是非空字段值:

//fetch c from the db...
Parent sameParent= new Parent;
sameParent.setWork(new Parent.Work());
//Directly from https://stackoverflow.com/questions/1301697/helper-in-order-to-copy-non-null-properties-from-object-to-another-java#answer-3521314
BeanUtilsBean notNull=new NullAwareBeanUtilsBean();
notNull.copyProperties(c, sameParent);

现在,Parent c 将拥有字段 age=55work.employer 字段将为空,因为对象 Work 已被覆盖。是否可以从 BeanUtilsBean 修改 @Override copyProperty 方法以递归地仅从包装对象中复制所需的(非空)属性?

要不然,你知道其他方法吗?

【问题讨论】:

  • 我也需要做类似的事情,但是,我在这里有一个疑问,尽管我们单独复制了那些具有非空值的属性,但是默认值为空的 java 引用类型。所以复制的bean对于你的例子会有“name”和birthDate的空值吗?那么我们如何避免这种情况呢?我被困在这里了。
  • 是的。在我的示例中,该字段的其余部分将具有空值。这是意料之中的,因为我没有在任何时候设置任何值。

标签: java apache-commons-beanutils


【解决方案1】:

您可以通过对 NullAwareBeanUtilsBean 的简单调整来实现这一点。我在这里所做的是检查要复制的属性的类型,如果它不是原始类型,则递归调用copyProperties 方法。 Java 自动装箱将原语转换为其包装类,因此我使用一组来识别原语类型。或者,您可以检查包的类类型以识别自定义对象,并仅对自定义进行递归调用,并避免所有 java 对象,如 String、Date 等。另请注意,此类不处理原始值。如果目标中的年龄设置为一个值并且源中的年龄未初始化,它仍将被覆盖。例如,如果源中的年龄设置为 20 并且未设置新对象的年龄,则复制会将值 20 覆盖为 0。您可能需要在 if-primitive 检查中添加额外的逻辑。

import java.lang.reflect.InvocationTargetException;
import java.util.HashSet;
import java.util.Set;

import org.apache.commons.beanutils.BeanUtilsBean;

public class NullAwareBeanUtilsBean extends BeanUtilsBean {
    private static final Set<Class<?>> primitiveTypes = new HashSet<Class<?>>(
    Arrays.asList(Boolean.class, Character.class, Byte.class, Short.class, Short.class, Integer.class, Long.class, Float.class, Double.class, Void.class, String.class, Date.class));

    private static final Set<Class<?>> primitiveTypes = new HashSet<Class<?>>() {
    {
        add(Boolean.class);
        add(Character.class);
        add(Byte.class);
        add(Short.class);
        add(Integer.class);
        add(Long.class);
        add(Float.class);
        add(Double.class);
        add(Void.class);
    }
    };

    @Override
    public void copyProperty(Object dest, String name, Object value)
        throws IllegalAccessException, InvocationTargetException {
    if (value == null)
        return;

    if (primitiveTypes.contains(value.getClass())) {
        super.copyProperty(dest, name, value);
    } else {
        try {
        Object childObj = getPropertyUtils().getSimpleProperty(dest, name);
        if (childObj == null || orig instanceof List && !((List)orig).isEmpty() && ((List)orig).get(0).getClass().isEnum()) {
            childObj=orig;
        }else{
            copyProperties(childObj, orig);
        }
        super.copyProperty(dest, name, childObj);
        } catch (NoSuchMethodException e) {
        e.printStackTrace();
        }
    }
    }
}

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-21
  • 1970-01-01
  • 2014-12-08
  • 2014-02-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多