Подтвердить что ты не робот

Помощник для копирования непустых свойств из объекта в другой? (Ява)

См. следующий класс

public class Parent {

    private String name;
    private int age;
    private Date birthDate;

    // getters and setters   

}

Предположим, что я создал родительский объект следующим образом

Parent parent = new Parent();

parent.setName("A meaningful name");
parent.setAge(20);

Обратите внимание, что в соответствии с кодом, приведенным выше, свойство birthDate равно null. Теперь я хочу копировать ТОЛЬКО ненулевые свойства от родительского объекта к другому. Что-то вроде

SomeHelper.copyNonNullProperties(parent, anotherParent);

Мне нужно это, потому что я хочу обновить объект anotherParent, не переопределяя его значение null с нулевыми значениями.

Знаете ли вы какого-нибудь помощника, подобного этому?

Я принимаю минимальный код в качестве ответа, не имеет ли в виду помощника

С уважением,

4b9b3361

Ответ 1

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

Вы пытались определить подкласс BeanUtilsBean пакета org.commons.beanutils? На самом деле, BeanUtils использует этот класс, поэтому это улучшение решения, предложенного dfa.

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

Что-то вроде этого:

package foo.bar.copy;
import java.lang.reflect.InvocationTargetException;
import org.apache.commons.beanutils.BeanUtilsBean;

public class NullAwareBeanUtilsBean extends BeanUtilsBean{

    @Override
    public void copyProperty(Object dest, String name, Object value)
            throws IllegalAccessException, InvocationTargetException {
        if(value==null)return;
        super.copyProperty(dest, name, value);
    }

}

Затем вы можете просто создать экземпляр NullAwareBeanUtilsBean и использовать его для копирования beans, например:

BeanUtilsBean notNull=new NullAwareBeanUtilsBean();
notNull.copyProperties(dest, orig);

Ответ 2

Если тип возвращаемого значения setter не является void, BeanUtils из Apache не будет работать, spring может. Итак, объедините два.

package cn.corpro.bdrest.util;

import org.apache.commons.beanutils.BeanUtilsBean;
import org.apache.commons.beanutils.ConvertUtilsBean;
import org.apache.commons.beanutils.PropertyUtilsBean;
import org.springframework.beans.BeanUtils;

import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;

/**
 * Author: [email protected]
 * DateTime: 2016/10/20 10:17
 */
public class MyBeanUtils {

    public static void copyPropertiesNotNull(Object dest, Object orig) throws InvocationTargetException, IllegalAccessException {
        NullAwareBeanUtilsBean.getInstance().copyProperties(dest, orig);
    }

    private static class NullAwareBeanUtilsBean extends BeanUtilsBean {

        private static NullAwareBeanUtilsBean nullAwareBeanUtilsBean;

        NullAwareBeanUtilsBean() {
            super(new ConvertUtilsBean(), new PropertyUtilsBean() {
                @Override
                public PropertyDescriptor[] getPropertyDescriptors(Class<?> beanClass) {
                    return BeanUtils.getPropertyDescriptors(beanClass);
                }

                @Override
                public PropertyDescriptor getPropertyDescriptor(Object bean, String name) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
                    return BeanUtils.getPropertyDescriptor(bean.getClass(), name);
                }
            });
        }

        public static NullAwareBeanUtilsBean getInstance() {
            if (nullAwareBeanUtilsBean == null) {
                nullAwareBeanUtilsBean = new NullAwareBeanUtilsBean();
            }
            return nullAwareBeanUtilsBean;
        }

        @Override
        public void copyProperty(Object bean, String name, Object value) throws IllegalAccessException, InvocationTargetException {
            if (value == null) return;
            super.copyProperty(bean, name, value);
        }
    }
}

Ответ 3

Просто используйте свой собственный метод копирования:

void copy(Object dest, Object source) throws IntrospectionException, IllegalArgumentException, IllegalAccessException,
        InvocationTargetException {
    BeanInfo beanInfo = Introspector.getBeanInfo(source.getClass());
    PropertyDescriptor[] pdList = beanInfo.getPropertyDescriptors();
    for (PropertyDescriptor pd : pdList) {
        Method writeMethod = null;
        Method readMethod = null;
        try {
            writeMethod = pd.getWriteMethod();
            readMethod = pd.getReadMethod();
        } catch (Exception e) {
        }

        if (readMethod == null || writeMethod == null) {
            continue;
        }

        Object val = readMethod.invoke(source);
        writeMethod.invoke(dest, val);
    }
}

Ответ 4

Использование PropertyUtils (commons-beanutils)

for (Map.Entry<String, Object> e : PropertyUtils.describe(parent).entrySet()) {
         if (e.getValue() != null && !e.getKey().equals("class")) {
                PropertyUtils.setProperty(anotherParent, e.getKey(), e.getValue());
         }
}

в Java8:

    PropertyUtils.describe(parent).entrySet().stream()
        .filter(e -> e.getValue() != null)
        .filter(e -> ! e.getKey().equals("class"))
        .forEach(e -> {
        try {
            PropertyUtils.setProperty(anotherParent, e.getKey(), e.getValue());
        } catch (Exception e) {
            // Error setting property ...;
        }
    });

Ответ 5

вы можете использовать Apache Common BeanUtils, более конкретно copyProperties помощник в классе BeanUtils:

 BeanUtils.copyProperties(parent, anotherParent);   

однако почему вы хотите копировать только ненулевые свойства? если свойство в parent равно null, просто копируя его, вы также имеете нулевое значение в anotherParent?

Просто гадать... вы хотите обновить bean другим bean?

Ответ 6

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

Если вы используете Spring, вы можете попробовать вариант ниже.

import java.beans.PropertyDescriptor;
import java.util.HashSet;
import java.util.Set;

import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;

/**
 * Helper class to extract property names from an object.
 * 
 * @Threadsafe
 * 
 * @author arun.bc
 * 
 */
public class PropertyUtil {

    /**
     * Gets the properties which have null values from the given object.
     * 
     * @param - source object
     * 
     * @return - String array of property names.
     */
    public static String[] getNullPropertiesString(Object source) {
        Set<String> emptyNames = getNullProperties(source);
        String[] result = new String[emptyNames.size()];

        return emptyNames.toArray(result);
    }


    /**
     * Gets the properties which have null values from the given object.
     * 
     * @param - source object
     * 
     * @return - Set<String> of property names.
     */
    public static Set<String> getNullProperties(Object source) {
        final BeanWrapper src = new BeanWrapperImpl(source);
        PropertyDescriptor[] pds = src.getPropertyDescriptors();

        Set<String> emptyNames = new HashSet<String>();
        for (PropertyDescriptor pd : pds) {
            Object srcValue = src.getPropertyValue(pd.getName());
            if (srcValue == null)
                emptyNames.add(pd.getName());
        }
        return emptyNames;
    }

    /**
     * Gets the properties which are not null from the given object.
     * 
     * @param - source object
     * 
     * @return - Set<String> array of property names.
     */
    public static Set<String> getNotNullProperties(Object source) {
        final BeanWrapper src = new BeanWrapperImpl(source);
        PropertyDescriptor[] pds = src.getPropertyDescriptors();

        Set<String> names = new HashSet<String>();
        for (PropertyDescriptor pd : pds) {
            Object srcValue = src.getPropertyValue(pd.getName());
            if (srcValue != null)
                names.add(pd.getName());
        }

        return names;
    }
}

Снова вы можете использовать PropertyDescriptor и Set из указанных выше методов для изменения объекта.