Helper afin de copier des propriétés non null d'un objet à un autre? (Java)

Voir la classe suivante

public class Parent {

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

    // getters and setters   

}

Supposons que j'ai créé un objet parent comme suit

Parent parent = new Parent();

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

avis selon le code ci-dessus la propriété date de naissance est nulle. Maintenant je veux copier seulement les propriétés non null de l'objet parent vers un autre. Quelque chose comme

SomeHelper.copyNonNullProperties(parent, anotherParent);

j'en ai besoin parce que je veux mettre à jour un autre objet parent sans outrepasser son non null avec des valeurs null.

connaissez vous des aide comme celle-ci ?

je accepter le code minimal comme réponse si aucun helper à l'esprit

cordialement,

24
demandé sur stian 2009-08-19 22:13:09

7 réponses

je suppose que vous avez déjà une solution, puisque beaucoup de temps s'est écoulé depuis que vous avez demandé. Cependant, il n'est pas marqué comme résolu, et peut-être que je peux aider d'autres utilisateurs.

avez-vous essayé de définir une sous-classe du BeanUtilsBeanorg.commons.beanutils package? Effectivement, BeanUtils utilise cette classe, il s'agit donc d'une amélioration de la solution proposée par dfa.

vérification à la code source de cette classe, je pense que vous pouvez écraser le copyProperty méthode, par vérification pour les valeurs null et ne rien faire si la valeur est null.

quelque Chose comme ceci :

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

}

alors vous pouvez instancier un NullAwareBeanUtilsBean et l'utiliser pour copier des haricots, par exemple:

BeanUtilsBean notNull=new NullAwareBeanUtilsBean();
notNull.copyProperties(dest, orig);
73
répondu SergiGS 2012-04-17 21:16:20

à l'Aide de PropertyUtils (communes-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());
         }
}
    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 ...;
        }
    });
3
répondu Lorenzo Luconi Trombacchi 2017-06-08 11:43:02

utilisez simplement votre propre méthode de copie:

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);
    }
}
2
répondu Mohsen 2012-09-05 13:34:45

si le type de retour de votre setter n'est pas nul, les BeanUtils D'Apache ne fonctionneront pas, le printemps peut. Alors combinez les deux.

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
répondu BaiJiFeiLong 2016-10-20 09:13:53

vous pouvez utiliser Apache Common BeanUtils, plus précisément l'aide copyProperties dans la classe de BeanUtils:

 BeanUtils.copyProperties(parent, anotherParent);   

cependant, pourquoi ne voulez-vous Copier que les propriétés non null? si une propriété parent est nulle, il vous suffit de copier ce que vous avez null également dans anotherParent droit?

juste une supposition... tu veux mettre à jour un haricot avec un autre haricot?

1
répondu dfa 2009-08-19 18:40:27

je sais que cette question est assez ancienne, mais j'ai pensé que la réponse ci-dessous pourrait être utile pour quelqu'un.

si vous utilisez Spring, vous pouvez essayer l'option ci-dessous.

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

Encore une fois, vous pouvez utiliser PropertyDescriptor et l'Ensemble des méthodes ci-dessus pour modifier l'objet.

0
répondu Arun B Chandrasekaran 2014-07-14 05:34:50
-1
répondu andersonbd1 2009-08-19 18:25:00