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,
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 BeanUtilsBean
org.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);
à 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 ...;
}
});
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);
}
}
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);
}
}
}
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?
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.
réflexion sur l'utilisation sûre: http://java.sun.com/developer/technicalArticles/ALT/Reflection/