Скопируйте содержимое POJO из одного компонента в другой

У меня есть несколько Pojos в разных пакетах, каждый POJO содержит набор другого pojo из того же пакета. Мне нужно скопировать все элементы с одинаковыми именами из пакета B Pojos в объекты в пакете A.

Пример:

package com.vanilla.packageA;

public class Student{

    private String firstName;
    private String lastName;
    private Set<Course> course;

    //getters and setters ommited

}   

package com.vanilla.packageA;

    public class Course{
    private String courseName;
    private String courseDescription;

    //seters and getters
}

package com.vanilla.packageB;

public class Student{

    private String firstName;
    private String lastName;
    private Address address;
    private Set<Course> course;
    Private Date birtday;

    //getters and setters ommited

}   

package com.vanilla.packageB;

public class Course{
    private String courseName;
    private String courseDescription;
    private <Lecturer> lecturer;
    private Integer hours;

    //seters and getters
} 

Я хочу рекурсивно скопировать все элементы из классов PackageB в классы packageA, которые существуют в PaCkageB и имеют одно и то же имя.

Обновления:

Ребята, я понимаю, что это глупый вопрос, но мне нужно поддерживать этот код, сейчас код написан так, что они должны вызывать 50 геттеров и сеттеров, или вызывать конструктор с 50 параметрами. К сожалению, я не могу использовать тот же объект, и мне нужно его скопировать, но я должен найти более «элегантный» способ скопировать эти бины.


person danny.lesnik    schedule 09.05.2011    source источник
comment
Похоже на странную просьбу. Вам нужен доступ к защищенным или стандартным методам/переменным?   -  person Qwerky    schedule 09.05.2011
comment
У меня есть геттеры и сеттеры, так что я могу их использовать.   -  person danny.lesnik    schedule 09.05.2011
comment
Я бы сказал, что у вас есть либо POJO, либо Bean. POJO — это аббревиатура от Plain Old Java Object. Имя используется, чтобы подчеркнуть, что данный объект является обычным объектом Java, а не специальным объектом и, в частности, не Enterprise JavaBean. из статьи в википедии POJO   -  person Peter Lawrey    schedule 09.05.2011
comment
Если вам не нужен доступ к материалам области пакета, то почему бы просто не использовать классы из пакета B? Нет причин, по которым вам нужно, чтобы классы были в пакете А.   -  person Qwerky    schedule 09.05.2011
comment
Пожалуйста, смотрите мое обновление, оно объяснит больше.   -  person danny.lesnik    schedule 09.05.2011
comment
@danny - Все еще не понимаю. Вы хотите сказать, что классы в пакете B слишком сложны и вам не нужны все 50 полей? Если есть конструктор по умолчанию (требуемый стандартами bean-компонентов), вы можете просто игнорировать те, которые вам не нужны.   -  person Qwerky    schedule 09.05.2011
comment
@Qwerky, вы правы, но если у этих классов 40 общих элементов, я не хочу вызывать сеттеры и геттеры 40 раз.   -  person danny.lesnik    schedule 09.05.2011


Ответы (8)


Любая причина, по которой Apache BeanUtils.copyProperties не работает?

person Rosdi Kasim    schedule 09.05.2011
comment
Будет ли apache BeanUtils копировать элементы из другого класса? Я всегда использовал его для копирования одних и тех же pojos одного и того же класса. - person danny.lesnik; 09.05.2011
comment
На самом деле это работает, если оба класса имеют одинаковые геттеры и сеттеры. - person Rosdi Kasim; 10.05.2011
comment
Однако BeanUtils не будет выполнять глубокое копирование. Так что вложенные bean-компоненты и т. д. не будут работать (как ни странно). - person Rob Grant; 27.08.2013
comment
У Beanutils есть сторонняя проблема, вы знаете другую альтернативу? - person TuGordoBello; 14.05.2018

Ну... Dozer может быть именно тем, что вам нужно.

. . . это объект для инфраструктуры сопоставления объектов. Идея в том, что:

  • Обычно он отображается по соглашению.
  • Вы можете переопределить это соглашение с помощью файла сопоставления.

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

Проводя учебные курсы SpringSource, мы очень часто указывали на эту структуру.

person flo    schedule 09.05.2011

См. mapstruct. Этот инструмент генерирует код, поэтому при отражении нет накладных расходов.

person FeelGood    schedule 13.02.2015

Если у вас уже есть весенние зависимости, вы можете использовать org.springframework.beans.BeanUtils

BeanUtils.copyProperties(from, to);
person user1121883    schedule 04.04.2019
comment
что, если мои атрибуты в разных случаях, любой вариант? - person Don Jose; 31.07.2019

Копирование значений полей необходимо почти в каждом проекте, например, для выполнения функции clone(). Я также думаю, что для достижения некоторых целей не обязательно импортировать .jars для использования только одной функции. Я хотел бы поделиться небольшим кодом, над которым я работал, есть некоторые вещи, которые я оставил в чернильнице, но в целом это работает. В этом случае я использую отражение.

public class ObjectCopyTools {

static String[] bases = new String[] {"byte", "short", "int", "long", "float", "double", "char", "boolean"};
static String[] equivalents = new String[] {"Byte", "Short", "Integer", "Long", "Float", "Double", "Character", "Boolean"};

static {

}

private static boolean areEquivalents(String type1, String type2){
    for (int i = 0; i < bases.length; i++) {
        if((type1.equals(bases[i]) && type2.equals(equivalents[i])) 
                || (type2.equals(bases[i]) && type1.equals(equivalents[i]))){
            return true;
        }
    }
    return false;
}

public static <T extends Object, Y extends Object> Y deepReflectionObjectCopy(T origin, Class<Y> resultClass) {
    Class<? extends Object> origClass = origin.getClass();
    Y resultObject = null;
    for (Constructor<?> constructor : resultClass.getConstructors()) {
        if (constructor.getParameterCount() == 0) {
            try {
                resultObject = (Y) constructor.newInstance();
            }catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
            }
            break;
        }
    }
    if(resultObject == null){
        return null;
    }
    Field[] origFields = origClass.getDeclaredFields();
    Field[] destFields = resultObject.getClass().getDeclaredFields();

    Object value = null;
    for(Field dstField: destFields){
        try {
            Field tempOrigField = origClass.getDeclaredField(dstField.getName());
            if(tempOrigField.getType().equals(dstField.getType())
                    || areEquivalents(tempOrigField.getType().getSimpleName(), dstField.getType().getSimpleName())){
                dstField.set(resultObject, tempOrigField.get(origin));
            }
        } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
        }
    }
    return resultObject;
}

Надеюсь, это поможет.

person Luis Carlos    schedule 04.06.2017
comment
есть ли какой-нибудь фрагмент кода, который вы забыли добавить, это не работает - я пытался, но не смог найти то, чего не хватает - person Ashish Shetkar; 27.11.2019
comment
Этот код работает для меня и является общим кодом, в нем нет каких-либо специальных или отсутствующих фрагментов кода. Не могли бы вы уточнить, почему у вас не работает? - person Luis Carlos; 26.12.2019

Если DRY — это основополагающий принцип компьютерных наук, то как вы можете объяснить наличие двух идентичных параллельных графов объектов? Вы не только удвоили нагрузку на техническое обслуживание, но теперь вам нужно разработать рекурсивный метод, который ничего не делает, кроме пересылки данных от одного к другому.

person duffymo    schedule 09.05.2011
comment
К сожалению, этот код не был разработан мной, я просто поддерживаю его сейчас. В настоящее время они используют конструкторы с 50 параметрами, которые они получили от другого класса. :) - person danny.lesnik; 09.05.2011
comment
Примером является код, сгенерированный веб-сервисами. В моем коде я должен запросить объект по идентификатору, используя getCustomerById(), а затем, чтобы обновить его, я должен сделать вызов setCustomer(CustomerUpdateRequest). getCustomerId возвращает CustomerResponse - все поля внутри являются строками/целыми/длинными или чем-то вроде AddressResponse. CustomerUpdateRequest содержит Strings/ints/longs и AddressRequest, но все имена полей одинаковы, до бесконечности! - person Rich; 19.09.2016

Используя PropertyUtils, вы можете скопировать только ненулевые свойства следующим образом:

    private void copyNonNullProperties(Object destination,
            Object source) {
        try {
            PropertyUtils.describe(source).entrySet().stream()
                    .filter(source -> source.getValue() != null)
                    .filter(source -> !source.getKey().equals("class"))
                    .forEach(source -> {
                        try {
                            PropertyUtils.setProperty(destination, source.getKey(), source.getValue());
                        } catch (Exception e22) {
                            log.error("Error setting properties : {}", e22.getMessage());
                        }
                    });

        } catch (Exception e1) {
            log.error("Error setting properties : {}", e1.getMessage());
        }

    }
person KayV    schedule 26.07.2019

Вы пытались использовать BULL? вы можете найти руководство по его использованию на DZone. Он предлагает возможность также выполнять преобразование объекта во время копирования. Более того, он выполняет копирование рекурсивно и не требует определения геттера и сеттера.

person Fabio Borriello    schedule 16.12.2020