次のクラスを参照してください
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です。次に、親オブジェクトから別のオブジェクトにnull以外のプロパティのみをコピーします。何かのようなもの
SomeHelper.copyNonNullProperties(parent, anotherParent);
Null値で非nullをオーバーライドせずに別のParentオブジェクトを更新したいので、それが必要です。
このようなヘルパーを知っていますか?
ヘルパーがいないかどうかの答えとして、最小限のコードを受け入れます
よろしく、
あなたが質問してからかなりの時間が経過したので、私はあなたがすでに解決策を持っていると思います。ただし、解決済みとはマークされておらず、他のユーザーを助けることができるかもしれません。
org.commons.beanutils
パッケージのBeanUtilsBean
のサブクラスを定義してみましたか?実際、BeanUtils
はこのクラスを使用するため、これはdfaによって提案されたソリューションの改良版です。
そのクラスの ソースコード を確認すると、copyProperty
メソッドを上書きできます。値がnullかどうかを確認し、値が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
をインスタンス化し、それを使用してBeanをコピーします。次に例を示します。
BeanUtilsBean notNull=new NullAwareBeanUtilsBean();
notNull.copyProperties(dest, orig);
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 ...;
}
});
単にあなた自身のコピー方法を使用してください:
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);
}
}
セッターの戻り型がvoidでない場合、ApacheのBeanUtilsは機能せず、Springが機能します。したがって、2つを組み合わせます。
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);
}
}
}
私は何年も後に解決策を見つけてここに着陸し、簡単なJavaリフレクションを使用してそれを達成しました。それが役に立てば幸いです!
public static void copyDiff(Product destination, Product source) throws
IllegalAccessException, NoSuchFieldException {
for (Field field : source.getClass().getDeclaredFields()) {
field.setAccessible(true);
String name = field.getName();
Object value = field.get(source);
//If it is a non null value copy to destination
if (null != value)
{
Field destField = destination.getClass().getDeclaredField(name);
destField.setAccessible(true);
destField.set(destination, value);
}
System.out.printf("Field name: %s, Field value: %s%n", name, value);
}
}
Apache Common BeanUtils 、より具体的には BeanUtilsクラスのcopyPropertiesヘルパー を使用できます。
BeanUtils.copyProperties(parent, anotherParent);
ただし、null以外のプロパティのみをコピーする必要があるのはなぜですか。 parent
のプロパティがnullの場合、単にコピーするだけで、anotherParent
にもnullがありますか?
推測してみてください... Beanを別のBeanで更新しますか?
この質問はかなり古いことを知っていますが、以下の答えが誰かに役立つかもしれないと思いました。
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を使用してオブジェクトを変更できます。