2016-12-13 3 views
1

내 목표는 한 개체의 필드를 다른 개체로 복사하는 것이지만 null이 아닌 개체 만 복사하는 것입니다. 명시 적으로 지정하고 싶지 않습니다. 보다 일반적인 솔루션은 매우 유용하고 유지하기 쉽습니다. 즉, 특정 필드 만 제공하도록 허용하는 REST API에서 PATCH를 구현하는 것입니다. BeanUtils 등을 사용하여 한 개체에서 다른 개체로 null이 아닌 속성 복사

나는이 비슷한 스레드를보고 여기에서 몇 가지 아이디어를 구현하기 위해 노력하고있어 : Helper in order to copy non null properties from object to another ? (Java)

을하지만 객체는 프로그램 실행 후 어떠한 방법 으로든 변경되지 않습니다.

그래서 여기 내 예를 들어 클래스, 예를 들어 생성됩니다 여기

class Person { 
public Person() { 
} 

public Person(String name, int age, Pet friend) { 
    this.name = name; 
    this.age = age; 
    this.friend = friend; 
} 

String name; 
int age; 
Pet friend; 

// getters and setters here 
} 

class Pet { 
public Pet(String name, int age) { 
    this.name = name; 
    this.age = age; 
} 

String name; 
int age; 

// getters and setters here 
} 

내 오버라이드 (override) copyProperty 방법 : 여기

import org.apache.commons.beanutils.BeanUtilsBean; 
import java.lang.reflect.InvocationTargetException; 

public class MyBeansUtil extends BeanUtilsBean { 

@Override 
public void copyProperty(Object dest, String name, Object value) 
     throws IllegalAccessException, InvocationTargetException { 
    if(value == null) return; 
    super.copyProperty(dest, name, value); 
} 
} 

... 그리고 내가 그것을 테스트하기 위해 노력하고있어 장소입니다 일부 예 :

public class SandBox { 
    public static void main(String[] args) { 
     Person db = new Person("John", 36, new Pet("Lucy", 3)); 
     Person db2 = new Person("John", 36, new Pet("Lucy", 2)); 
     Person db3 = new Person("John", 36, new Pet("Lucy", 4)); 

     Person in = new Person(); 
     in.age = 17; 
     in.name = "Paul"; 
     in.friend = new Pet(null, 35); 

     Person in2 = new Person(); 
     in2.name = "Damian"; 

     Person in3 = new Person(); 
     in3.friend = new Pet("Lup", 25); 

     try { 
      BeanUtilsBean notNull =new MyBeansUtil(); 
      notNull.copyProperties(db, in); 
      notNull.copyProperties(db2, in2); 
      notNull.copyProperties(db3, in3); 

     } catch (IllegalAccessException e) { 
      e.printStackTrace(); 
     } catch (InvocationTargetException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

불행히도 원래 개체 db, db1, db2는 있었어. 내가 여기서 뭔가 잘못하고있는거야?

+1

클래스 선언의 액세스 수정자가 작동하도록 public으로 변경하십시오. public class Person {}이이 문제를 해결할 것입니다 – Nagaraddi

+0

답변을 주셔서 감사합니다 - 저는 이미 apache.commons.beanutilsbean에 대한 의존성을 피하기 때문에 저에게 더 나은 해결책을 찾았습니다. 이제는 두 가지 방법을 모두 알고 있습니다. – kiedysktos

+0

@kiedysktos 비슷한 유스 케이스가 있는데 다른 솔루션이 어떻게 작동했는지 알고 싶습니다. 당신이 그것을 정교 할 수 있다면, 그것은 위대 할 것입니다 :) – hardcoder

답변

2

Spring BeanUtils 라이브러리를 사용하여 종료했습니다.

import org.springframework.beans.BeanWrapper; 
import org.springframework.beans.BeanWrapperImpl; 

import java.lang.reflect.Field; 
import java.util.Collection; 

public class MyBeansUtil<T> { 
    public T copyNonNullProperties(T target, T in) { 
     if (in == null || target == null || target.getClass() != in.getClass()) return null; 

     final BeanWrapper src = new BeanWrapperImpl(in); 
     final BeanWrapper trg = new BeanWrapperImpl(target); 

     for (final Field property : target.getClass().getDeclaredFields()) { 
      Object providedObject = src.getPropertyValue(property.getName()); 
      if (providedObject != null && !(providedObject instanceof Collection<?>)) { 
       trg.setPropertyValue(
         property.getName(), 
         providedObject); 
      } 
     } 
     return target; 
    } 
} 

그것은 잘 작동하지만 컬렉션있는 필드를 무시 통지 : 여기 내 작업 방법입니다. 그것은 의도적으로, 나는 그것들을 개별적으로 다룬다.

0

null 값을 무시하면서 속성을 복사하는 고유 한 메서드를 만들 수 있습니다.

public static String[] getNullPropertyNames (Object source) { 
    final BeanWrapper src = new BeanWrapperImpl(source); 
    java.beans.PropertyDescriptor[] pds = src.getPropertyDescriptors(); 

    Set<String> emptyNames = new HashSet<String>(); 
    for(java.beans.PropertyDescriptor pd : pds) { 
     Object srcValue = src.getPropertyValue(pd.getName()); 
     if (srcValue == null) emptyNames.add(pd.getName()); 
    } 
    String[] result = new String[emptyNames.size()]; 
    return emptyNames.toArray(result); 
} 

// then use Spring BeanUtils to copy and ignore null 
public static void myCopyProperties(Object src, Object target) { 
    BeanUtils.copyProperties(src, target, getNullPropertyNames(src)) 
}