Helper per copiare proprietà non nulle da un object all’altro? (Giava)

Vedi la seguente class

public class Parent { private String name; private int age; private Date birthDate; // getters and setters } 

Supponiamo di aver creato un object genitore come segue

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

Avviso secondo il codice sopra la proprietà birthDate è nullo. Ora voglio copiare SOLO proprietà non nulle dall’object padre a un altro. Qualcosa di simile a

 SomeHelper.copyNonNullProperties(parent, anotherParent); 

Ne ho bisogno perché voglio aggiornare un object anotherParent senza sovrascrivere il suo valore non nullo con valori nulli.

Conosci qualche aiutante come questo?

Accetto codice minimale come risposta se nessun helper in mente

Saluti,

Suppongo che tu abbia già una soluzione, poiché è passato molto tempo da quando hai chiesto. Tuttavia, non è contrassegnato come risolto e forse posso aiutare altri utenti.

Hai provato definendo una sottoclass di BeanUtilsBean del pacchetto org.commons.beanutils ? In realtà, BeanUtils utilizza questa class, quindi questo è un miglioramento della soluzione proposta da dfa.

Controllando il codice sorgente di quella class, penso che si possa sovrascrivere il metodo copyProperty , controllando i valori nulli e non facendo nulla se il valore è nullo.

Qualcosa come questo :

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

Quindi puoi semplicemente istanziare un NullAwareBeanUtilsBean e usarlo per copiare i tuoi bean, ad esempio:

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

Uso di PropertyUtils (commons-beanutils)

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

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

Usa semplicemente il tuo metodo di copia:

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

Se il tipo di reso del tuo setter non è nullo, BeanUtils di Apache non funzionerà, molla può. Quindi unisci i due.

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

è ansible utilizzare Apache Common BeanUtils , in particolare l’helper copyProperties nella class BeanUtils :

  BeanUtils.copyProperties(parent, anotherParent); 

tuttavia perché vuoi copiare solo proprietà non nulle? se una proprietà in parent è null, semplicemente copiandola hai anche null in anotherParent vero?

Solo supposizioni … vuoi aggiornare un bean con un altro bean?

Conosco il fatto che questa domanda è piuttosto vecchia, ma ho pensato che la risposta qui sotto potrebbe essere utile per qualcuno.

Se usi Spring, puoi provare l’opzione seguente.

 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 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 of property names. */ public static Set getNullProperties(Object source) { final BeanWrapper src = new BeanWrapperImpl(source); PropertyDescriptor[] pds = src.getPropertyDescriptors(); Set emptyNames = new HashSet(); 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 array of property names. */ public static Set getNotNullProperties(Object source) { final BeanWrapper src = new BeanWrapperImpl(source); PropertyDescriptor[] pds = src.getPropertyDescriptors(); Set names = new HashSet(); for (PropertyDescriptor pd : pds) { Object srcValue = src.getPropertyValue(pd.getName()); if (srcValue != null) names.add(pd.getName()); } return names; } } 

Anche in questo caso è ansible utilizzare PropertyDescriptor e il Set dai metodi precedenti per modificare l’object.