BeanUtils.copyProperties缺少深层嵌套变量?

时间:2022-09-11 18:47:55

I'm using BeanUtils.copyProperties to copy the entire content of one object into another that inherit from it.

我正在使用BeanUtils.copyProperties将一个对象的整个内容复制到另一个继承自它的对象中。

Here is the context, the domain object from which the values are copied contains a Set of objects of custom type Xref. That custom type has an embedded class with various fields of various class types.

以下是上下文,从中复制值的域对象包含一组自定义类型为Xref的对象。该自定义类型具有嵌入类,其具有各种类类型的各种字段。

For some reason one of the field from an object encapsulated within the embedded object does not get copied over. But most everything else I need do get copied over.

由于某种原因,封装在嵌入对象中的对象中的一个字段不会被复制。但是我需要的大多数其他东西都被复制了。

With an example:

举个例子:

class Source {
private Set<Xref> xref;
...
}

class Xref {
...
public static class primaryKey {
...
private MyObj obj;
}
}

class MyObj {
private Integer id;
...
}

Using those names if I try to use BeanUtils.copyProperties to copy the content of a "Source" object into a "SourceExtended" object the value of source.xrefs.get(0).getPrimaryKey().getObj().getId() does not get copied over. In the original object it has a value but in the target object it's null...

如果我尝试使用BeanUtils.copyProperties将“Source”对象的内容复制到“SourceExtended”对象中,则使用这些名称source.xrefs.get(0).getPrimaryKey()。getObj()。getId()的值不会被复制。在原始对象中它有一个值,但在目标对象中它是null ...

Any idea why???

知道为什么???

Thank you.

2 个解决方案

#1


From the Javadocs:

来自Javadocs:

Note that this method is intended to perform a "shallow copy" of the properties and so complex properties (for example, nested ones) will not be copied.

请注意,此方法旨在执行属性的“浅层复制”,因此不会复制复杂属性(例如,嵌套的属性)。

#2


Here's how I handle this with Spring. Might be of some help. My method is a copy of Spring's shallowCopyFieldState but allows the use of a field filter. Ignores statics and finals.

这是我用Spring处理这个问题的方法。可能会有所帮助。我的方法是Spring的shallowCopyFieldState的副本,但允许使用字段过滤器。忽略静态和决赛。

My method

public static void shallowCopyFieldState(final Object src, final Object dest, final FieldFilter filter)
        throws IllegalArgumentException {
    if (src == null) {
        throw new IllegalArgumentException("Source for field copy cannot be null");
    }
    if (dest == null) {
        throw new IllegalArgumentException("Destination for field copy cannot be null");
    }
    if (!src.getClass().isAssignableFrom(dest.getClass())) {
        throw new IllegalArgumentException("Destination class [" + dest.getClass().getName()
                + "] must be same or subclass as source class [" + src.getClass().getName() + "]");
    }
    org.springframework.util.ReflectionUtils.doWithFields(src.getClass(),
            new org.springframework.util.ReflectionUtils.FieldCallback() {
                public void doWith(final Field field) throws IllegalArgumentException, IllegalAccessException {
                    org.springframework.util.ReflectionUtils.makeAccessible(field);
                    final Object srcValue = field.get(src);
                    field.set(dest, srcValue);
                }
            }, filter);
}

Spring's doWithFields:

/**
 * Invoke the given callback on all fields in the target class,
 * going up the class hierarchy to get all declared fields.
 * @param targetClass the target class to analyze
 * @param fc the callback to invoke for each field
 * @param ff the filter that determines the fields to apply the callback to
 */
public static void doWithFields(Class targetClass, FieldCallback fc, FieldFilter ff)
        throws IllegalArgumentException {

    // Keep backing up the inheritance hierarchy.
    do {
        // Copy each field declared on this class unless it's static or file.
        Field[] fields = targetClass.getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            // Skip static and final fields.
            if (ff != null && !ff.matches(fields[i])) {
                continue;
            }
            try {
                fc.doWith(fields[i]);
            }
            catch (IllegalAccessException ex) {
                throw new IllegalStateException(
                        "Shouldn't be illegal to access field '" + fields[i].getName() + "': " + ex);
            }
        }
        targetClass = targetClass.getSuperclass();
    }
    while (targetClass != null && targetClass != Object.class);
}

#1


From the Javadocs:

来自Javadocs:

Note that this method is intended to perform a "shallow copy" of the properties and so complex properties (for example, nested ones) will not be copied.

请注意,此方法旨在执行属性的“浅层复制”,因此不会复制复杂属性(例如,嵌套的属性)。

#2


Here's how I handle this with Spring. Might be of some help. My method is a copy of Spring's shallowCopyFieldState but allows the use of a field filter. Ignores statics and finals.

这是我用Spring处理这个问题的方法。可能会有所帮助。我的方法是Spring的shallowCopyFieldState的副本,但允许使用字段过滤器。忽略静态和决赛。

My method

public static void shallowCopyFieldState(final Object src, final Object dest, final FieldFilter filter)
        throws IllegalArgumentException {
    if (src == null) {
        throw new IllegalArgumentException("Source for field copy cannot be null");
    }
    if (dest == null) {
        throw new IllegalArgumentException("Destination for field copy cannot be null");
    }
    if (!src.getClass().isAssignableFrom(dest.getClass())) {
        throw new IllegalArgumentException("Destination class [" + dest.getClass().getName()
                + "] must be same or subclass as source class [" + src.getClass().getName() + "]");
    }
    org.springframework.util.ReflectionUtils.doWithFields(src.getClass(),
            new org.springframework.util.ReflectionUtils.FieldCallback() {
                public void doWith(final Field field) throws IllegalArgumentException, IllegalAccessException {
                    org.springframework.util.ReflectionUtils.makeAccessible(field);
                    final Object srcValue = field.get(src);
                    field.set(dest, srcValue);
                }
            }, filter);
}

Spring's doWithFields:

/**
 * Invoke the given callback on all fields in the target class,
 * going up the class hierarchy to get all declared fields.
 * @param targetClass the target class to analyze
 * @param fc the callback to invoke for each field
 * @param ff the filter that determines the fields to apply the callback to
 */
public static void doWithFields(Class targetClass, FieldCallback fc, FieldFilter ff)
        throws IllegalArgumentException {

    // Keep backing up the inheritance hierarchy.
    do {
        // Copy each field declared on this class unless it's static or file.
        Field[] fields = targetClass.getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            // Skip static and final fields.
            if (ff != null && !ff.matches(fields[i])) {
                continue;
            }
            try {
                fc.doWith(fields[i]);
            }
            catch (IllegalAccessException ex) {
                throw new IllegalStateException(
                        "Shouldn't be illegal to access field '" + fields[i].getName() + "': " + ex);
            }
        }
        targetClass = targetClass.getSuperclass();
    }
    while (targetClass != null && targetClass != Object.class);
}