web-dev-qa-db-ja.com

null以外のプロパティをオブジェクトから別のプロパティにコピーするためのヘルパー? (Java)

次のクラスを参照してください

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オブジェクトを更新したいので、それが必要です。

このようなヘルパーを知っていますか?

ヘルパーがいないかどうかの答えとして、最小限のコードを受け入れます

よろしく、

41
Arthur Ronald

あなたが質問してからかなりの時間が経過したので、私はあなたがすでに解決策を持っていると思います。ただし、解決済みとはマークされておらず、他のユーザーを助けることができるかもしれません。

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);
91
SergiGS

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

セッターの戻り型が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);
        }
    }
}
2
BaiJiFeiLong

私は何年も後に解決策を見つけてここに着陸し、簡単な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);
   }
}
1
samairtimer

Apache Common BeanUtils 、より具体的には BeanUtilsクラスのcopyPropertiesヘルパー を使用できます。

 BeanUtils.copyProperties(parent, anotherParent);   

ただし、null以外のプロパティのみをコピーする必要があるのはなぜですか。 parentのプロパティがnullの場合、単にコピーするだけで、anotherParentにもnullがありますか?

推測してみてください... Beanを別のBeanで更新しますか?

0
dfa

この質問はかなり古いことを知っていますが、以下の答えが誰かに役立つかもしれないと思いました。

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を使用してオブジェクトを変更できます。