web-dev-qa-db-fra.com

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 naissanceDate propriété est null. Maintenant, je veux copier UNIQUEMENT les propriétés non null d'un objet parent à un autre. Quelque chose comme

SomeHelper.copyNonNullProperties(parent, anotherParent);

J'en ai besoin parce que je veux mettre à jour un autre objet sans remplacer ses valeurs non nulles avec des valeurs nulles.

Connaissez-vous un assistant comme celui-ci?

J'accepte le code minimal comme réponse si aucune aide en tête

cordialement,

27
Arthur Ronald

Je suppose que vous avez déjà une solution, car il s'est passé beaucoup de temps depuis votre demande. Cependant, cela n'est pas indiqué comme résolu, et je peux peut-être aider d'autres utilisateurs.

Avez-vous essayé de définir une sous-classe de la BeanUtilsBean du paquetage org.commons.beanutils? En fait, BeanUtils utilise cette classe. Il s’agit donc d’une amélioration de la solution proposée par dfa.

En vérifiant le code source de cette classe, je pense que vous pouvez écraser la méthode copyProperty en vérifiant les valeurs NULL et en ne faisant rien si la valeur est null.

Quelque chose comme ça :

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

}

Ensuite, vous pouvez simplement instancier une NullAwareBeanUtilsBean et l’utiliser pour copier vos beans, par exemple:

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

Utilisation de 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());
         }
}

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

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
Mohsen

Si le type de retour de votre donneur n'est pas annulé, BeanUtils of Apache ne fonctionnera 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: [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);
        }
    }
}
2
BaiJiFeiLong

vous pouvez utiliser Apache Common BeanUtils , plus précisément l’assistant copyProperties de la classe BeanUtils :

 BeanUtils.copyProperties(parent, anotherParent);   

cependant, pourquoi voulez-vous copier uniquement les propriétés non NULL? si une propriété dans parent est null, en la copiant simplement, vous avez également null dans anotherParent right?

Juste deviner ... vous voulez mettre à jour un haricot avec un autre haricot?

1
dfa

Je sais que cette question est assez ancienne, mais j’ai pensé que la réponse ci-dessous pourrait être utile à 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