2009-08-19 7 views
23

Voir la classe suivanteAide pour copier des propriétés non nulles d'un objet à un autre? (Java)

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 propriété birthDate est nulle. Maintenant, je veux copier seulement les propriétés non nulles de l'objet parent à l'autre. Quelque chose comme

SomeHelper.copyNonNullProperties(parent, anotherParent); 

je en ai besoin parce que je veux mettre à jour l'objet anotherParent sans dérogations sa non nulle avec des valeurs nulles.

Connaissez-vous un assistant comme celui-ci?

J'accepte un minimum de code comme réponse si pas d'aide à l'esprit

salutations

+0

tag ressort Retiré de celui-ci, car il n'a rien à voir avec le printemps. – Trenton

+0

Suppression de la balise hibernate, car elle n'a rien à voir avec hibernate non plus. – stian

Répondre

68

Je suppose que vous avez déjà une solution, car il s'est passé beaucoup de temps 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é en définissant une sous-classe du BeanUtilsBean du package org.commons.beanutils? En fait, BeanUtils utilise cette classe, donc c'est une amélioration de la solution proposée par dfa.

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

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 juste instancier un NullAwareBeanUtilsBean et l'utiliser pour copier vos haricots, par exemple:

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

une réponse idéale utiliserait l'exemple de classe parent fourni dans la question – kiedysktos

+0

J'essaie de mettre en œuvre vos idées, mais pas de succès jusqu'à présent. J'ai créé un fil pour cela http://stackoverflow.com/questions/41125384/copy-non-null-properties-from-one-object-to-another-using-beanutilsbean – kiedysktos

+1

copyProperty() est la méthode statique http: // commons.apache.org/proper/commons-beanutils/javadocs/v1.9.3/apidocs/index.html – Sadanand

0

vous pouvez utiliser Apache Common BeanUtils, plus particulièrement the copyProperties helper in BeanUtils class:

BeanUtils.copyProperties(parent, anotherParent); 

Cependant, pourquoi voulez-vous copier uniquement les propriétés non nulles? si une propriété dans parent est nulle, en le copiant simplement vous avez également zéro dans anotherParent droite?

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

+1

Oui, je veux mettre à jour un autre bean sans substituer ses valeurs non nulles. –

+1

+ 1 pour une suggestion saine d'utiliser des bibliothèques ... parfois je me sens comme nous sommes les voix solitaires dans le désert sur celui-ci – skaffman

+2

Salut, désolé mais cela ne fonctionne pas. Si j'ai un otherParent.getBirthDate() non nul et j'appelle BeanUtils.copyProperties (parent, anotherParent) anotherParent.getBirthDate() renverra null –

1

suffit d'utiliser 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); 
    } 
} 
0

Je sais que cette question est assez ancienne, mais je pensais que le belo w réponse peut ê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.

2

Si le type de retour de votre setter n'est pas vide, BeanUtils d'Apache ne fonctionnera pas, spring can. 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

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

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