В BeanUtils.copyProperties отсутствуют глубоко вложенные переменные?
Я использую BeanUtils.copyProperties для копирования всего содержимого одного объекта в другой, который наследуется от него.
Вот контекст, объект домена, из которого копируются значения, содержит набор объектов пользовательского типа Xref. Этот пользовательский тип имеет встроенный класс с различными полями различных типов классов.
По какой-то причине одно из полей объекта, инкапсулированного во встроенный объект, не копируется. Но все остальное, что мне нужно, скопировано.
С примером:
class Source {
private Set<Xref> xref;
...
}
class Xref {
...
public static class primaryKey {
...
private MyObj obj;
}
}
class MyObj {
private Integer id;
...
}
Используя эти имена, если я пытаюсь использовать BeanUtils.copyProperties для копирования содержимого объекта "Source" в объект "SourceExtended", значение source.xrefs.get(0).getPrimaryKey(). GetObj(). GetId() не копируется. В исходном объекте оно имеет значение, но в целевом объекте оно равно нулю...
Есть идеи почему???
Спасибо.
2 ответа
Из Javadocs:
Обратите внимание, что этот метод предназначен для выполнения "мелкой копии" свойств, и поэтому сложные свойства (например, вложенные) не будут скопированы.
Вот как я справляюсь с этим с помощью Spring. Может быть, поможет Мой метод является копией Spring shallowCopyFieldState, но позволяет использовать фильтр поля. Игнорирует статики и финалы.
Мой метод
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);
}