Помощник для того, чтобы скопировать ненулевые свойства из объекта в другой? (Джава) - PullRequest
32 голосов
/ 19 августа 2009

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

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.

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

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

С уважением,

Ответы [ 6 ]

82 голосов
/ 19 августа 2010

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

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

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

Примерно так:

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 и использовать его для копирования ваших бинов, например:

BeanUtilsBean notNull=new NullAwareBeanUtilsBean();
notNull.copyProperties(dest, orig);
3 голосов
/ 08 июня 2017

Использование 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 ...;
        }
    });
2 голосов
/ 20 октября 2016

Если тип возврата вашего установщика не является пустым, 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: BaiJiFeiLong@gmail.com
 * 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);
        }
    }
}
2 голосов
/ 05 сентября 2012

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

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);
    }
}
0 голосов
/ 14 июля 2014

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

Если вы используете 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 из вышеперечисленных методов для изменения объекта.

0 голосов
/ 19 августа 2009

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

 BeanUtils.copyProperties(parent, anotherParent);   

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...