Как скопировать свойства из одного компонента Java в другой? - PullRequest
14 голосов
/ 07 мая 2009

У меня есть простой Java POJO, который я бы скопировал свойства в другой экземпляр того же класса POJO.

Я знаю, что могу сделать это с помощью BeanUtils.copyProperties (), но я бы хотел избежать использования сторонней библиотеки.

Итак, как сделать это просто, правильным и безопасным способом?

Кстати, я использую Java 6.

Ответы [ 8 ]

12 голосов
/ 07 мая 2009

Полагаю, если вы посмотрите на исходный код BeanUtils, он покажет вам, как это сделать, фактически не используя BeanUtils.

Если вы просто хотите создать копию POJO (не совсем то же самое, что копирование свойств из одного POJO в другой), вы можете изменить исходный компонент для реализации метода clone () и интерфейса Cloneable.

11 голосов
/ 21 октября 2011

У меня была такая же проблема при разработке приложения для Google App Engine, где я не мог использовать BeanUtils из-за ограничений ведения журналов общего доступа. Во всяком случае, я придумала это решение и отлично работала для меня.

public static void copyProperties(Object fromObj, Object toObj) {
    Class<? extends Object> fromClass = fromObj.getClass();
    Class<? extends Object> toClass = toObj.getClass();

    try {
        BeanInfo fromBean = Introspector.getBeanInfo(fromClass);
        BeanInfo toBean = Introspector.getBeanInfo(toClass);

        PropertyDescriptor[] toPd = toBean.getPropertyDescriptors();
        List<PropertyDescriptor> fromPd = Arrays.asList(fromBean
                .getPropertyDescriptors());

        for (PropertyDescriptor propertyDescriptor : toPd) {
            propertyDescriptor.getDisplayName();
            PropertyDescriptor pd = fromPd.get(fromPd
                    .indexOf(propertyDescriptor));
            if (pd.getDisplayName().equals(
                    propertyDescriptor.getDisplayName())
                    && !pd.getDisplayName().equals("class")) {
                 if(propertyDescriptor.getWriteMethod() != null)                
                         propertyDescriptor.getWriteMethod().invoke(toObj, pd.getReadMethod().invoke(fromObj, null));
            }

        }
    } catch (IntrospectionException e) {
        e.printStackTrace();
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    }
}

Любые улучшения или рекомендации действительно приветствуются.

3 голосов
/ 07 февраля 2014

Эй, друзья, просто используйте мой созданный класс ReflectionUtil для копирования значений одного компонента в другой аналогичный компонент. Этот класс также будет копировать объект Коллекции.

https://github.com/vijayshegokar/Java/blob/master/Utility/src/common/util/reflection/ReflectionUtil.java

Примечание: Этот бин должен иметь аналогичное имя переменной с типом и иметь для него методы getter и setters.

Теперь добавлены дополнительные функции. Вы также можете скопировать данные одного объекта в его bean-компонент. Если у одной сущности есть другая сущность, то вы можете передать опцию карты для изменения внутренней сущности во время выполнения связанному с ней бину.

Например.

ParentEntity parentEntityObject = getParentDataFromDB();
Map<Class<?>, Class<?>> map = new HashMap<Class<?>, Class<?>>();
map.put(InnerBean1.class, InnerEntity1.class);
map.put(InnerBean2.class, InnerEntity2.class);
ParentBean parent = ReflectionUtil.copy(ParentBean.class, parentEntityObject, map);

Этот случай очень полезен, когда ваши сущности содержат отношения.

3 голосов
/ 09 июля 2013

Другой альтернативой является MapStruct , который генерирует код отображения во время сборки, что приводит к безопасным типам отображений, которые не требуют никаких зависимостей во время выполнения (Отказ от ответственности: я автор MapStruct). *

2 голосов
/ 07 мая 2009

Посмотрите на JavaBeans API , в частности класс Introspector . Вы можете использовать метаданные BeanInfo для get и set свойств. Хорошей идеей будет прочитать спецификацию JavaBeans , если вы этого еще не сделали. Также полезно познакомиться с API отражения 1012 *.

1 голос
/ 05 декабря 2011

Я столкнулся с некоторыми проблемами с Introspector.getBeanInfo, не возвращающими все свойства, поэтому я в итоге реализовал копию поля вместо копии свойства.

public static <T> void copyFields(T target, T source) throws Exception{
    Class<?> clazz = source.getClass();

    for (Field field : clazz.getFields()) {
        Object value = field.get(source);
        field.set(target, value);
    }
}
1 голос
/ 07 мая 2009

Там - это простого способа сделать это. Библиотеки Introspector и Java bean являются монолитными - BeanUtils - простая оболочка для этого и хорошо работает. Отсутствие библиотек просто для того, чтобы не иметь библиотек, является в целом плохой идеей - для этого есть одна причина, с которой стоит начать - общая функциональность, которая должна существовать в Java, но ее нет.

0 голосов
/ 10 июля 2017

Вы можете достичь этого, используя Java Reflection API .

public static <T> void copy(T target, T source) throws Exception {
    Class<?> clazz = source.getClass();

    for (Field field : clazz.getDeclaredFields()) {
        if (Modifier.isPrivate(field.getModifiers()))
            field.setAccessible(true);
        Object value = field.get(source);
        field.set(target, value);
    }
}
...