Помощник для копирования непустых свойств из объекта в другой? (Ява)
См. следующий класс
public class Parent {
private String name;
private int age;
private Date birthDate;
// getters and setters
}
Предположим, что я создал родительский объект следующим образом
Parent parent = new Parent();
parent.setName("A meaningful name");
parent.setAge(20);
Обратите внимание, что в соответствии с кодом, приведенным выше, свойство birthDate равно null. Теперь я хочу копировать ТОЛЬКО ненулевые свойства от родительского объекта к другому. Что-то вроде
SomeHelper.copyNonNullProperties(parent, anotherParent);
Мне нужно это, потому что я хочу обновить объект anotherParent, не переопределяя его значение null с нулевыми значениями.
Знаете ли вы какого-нибудь помощника, подобного этому?
Я принимаю минимальный код в качестве ответа, не имеет ли в виду помощника
С уважением,
Ответы
Ответ 1
Я полагаю, что у вас уже есть решение, поскольку с тех пор прошло много времени. Однако он не помечен как решенный, и, возможно, я могу помочь другим пользователям.
Вы пытались определить подкласс BeanUtilsBean
пакета org.commons.beanutils
? На самом деле, BeanUtils
использует этот класс, поэтому это улучшение решения, предложенного dfa.
Проверяя в исходный код этого класса, я думаю, вы можете перезаписать метод copyProperty
, проверив нулевые значения и ничего не делая если значение равно null.
Что-то вроде этого:
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);
}
}
Затем вы можете просто создать экземпляр NullAwareBeanUtilsBean
и использовать его для копирования beans, например:
BeanUtilsBean notNull=new NullAwareBeanUtilsBean();
notNull.copyProperties(dest, orig);
Ответ 2
Если тип возвращаемого значения setter не является void, BeanUtils из Apache не будет работать, spring может. Итак, объедините два.
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);
}
}
}
Ответ 3
Просто используйте свой собственный метод копирования:
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);
}
}
Ответ 4
Использование 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());
}
}
в 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 ...;
}
});
Ответ 5
вы можете использовать Apache Common BeanUtils, более конкретно copyProperties помощник в классе BeanUtils:
BeanUtils.copyProperties(parent, anotherParent);
однако почему вы хотите копировать только ненулевые свойства? если свойство в parent
равно null, просто копируя его, вы также имеете нулевое значение в anotherParent
?
Просто гадать... вы хотите обновить bean другим bean?
Ответ 6
Я знаю, что этот вопрос довольно старый, но я думал, что нижеприведенный ответ может быть полезен для кого-то.
Если вы используете Spring, вы можете попробовать вариант ниже.
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;
}
}
Снова вы можете использовать PropertyDescriptor и Set из указанных выше методов для изменения объекта.
Ответ 7
уверен - используйте отражение:
http://java.sun.com/developer/technicalArticles/ALT/Reflection/