Как скопировать свойства с одного Java bean в другое?

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

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

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

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

Ответы

Ответ 1

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

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

Ответ 2

У меня возникла такая же проблема при разработке приложения для 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

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

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

Примечание: Этот bean должен иметь схожие имена переменных с типом и иметь для них getter и seters.

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

Eg.

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);

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

Ответ 4

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

Ответ 5

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

Ответ 6

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

Ответ 7

Я столкнулся с некоторыми проблемами, когда 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);
    }
}

Ответ 8

Вы можете достичь этого, используя API 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);
    }
}