2014-07-21 3 views
4

두 개의 자바 객체가 있고 그것들을 단일 객체로 병합하고 싶습니다. 문제는 두 객체가 복잡한 유형 속성 (다른 유형의 객체 및 다른 유형의 객체 목록과 같은)을 포함하는 일반 기본 유형 속성 (필드)을 포함하지 않는다는 것입니다.자바에서 두 개의 복잡한 객체를 병합하는 방법

개체 1 : 일부 속성 (필드)와

객체이 설정하여 반환 값 : 일부 속성을 설정하여 수익을 (필드) 또는 그것이 보유하고 있지만, 개체에 의해 반환되지 유형의 새 개체를 반환 할 수 있습니다 1.

오브젝트 1과 오브젝트 2는 모두 같은 유형입니다. 2 obj를 같은 종류가 obj2보다

+0

귀하의 노력을 보여주십시오. 지금까지 무엇을 시도 했습니까? –

+0

이 클래스와 특히이 메소드를 살펴보십시오. http://docs.spring.io/spring/docs/2.5.6/api/org/springframework/beans/BeanUtils.html#copyProperties(java.lang.Object, java. lang.Object) –

답변

2

시도에서 OBJ1 + 새 업데이트 된 개체로 class.getFields

Field[] fields = YourClass.getFields(); 
    for (Field field : fields) { 
     // get value 
     YourObject value = field.get(objectInstance); 
     // check the values are different, then update 
     field.set(objetInstance, value);  
    } 
+0

감사합니다. tokhi하지만 복잡성의 한 단계에서만 작동합니다. – user3860615

+0

하지만 내부 레벨에 대해서도 같은 것을 사용할 수 있습니다. – tokhi

13

를 사용하는 경우에서

결과 개체 3 =으로 obj1 속성 + 속성을 업데이트 그것을 사용 할 아주 쉽게 봄에 의해 제공되는 org.springframework.beans.BeanUtils 클래스. 아니면 Apache Commons BeanUtils library 나는 스프링 버전 중 하나를 기반으로 생각하거나 동일합니다.

을 : 당신은 캔트 또는 NOARGS 생성자를 해달라고 경우가 null 속성이 같은 것을 사용할 수 있습니다 복사 싶지 않는 경우

public static <T> T combine2Objects(T a, T b) throws InstantiationException, IllegalAccessException { 
    // would require a noargs constructor for the class, maybe you have a different way to create the result. 
    T result = (T) a.getClass().newInstance(); 
    BeanUtils.copyProperties(a, result); 
    BeanUtils.copyProperties(b, result); 
    return result; 
} 

어쩌면 당신은 결과

public static <T> T combine2Objects(T a, T b, T destination) { 
    BeanUtils.copyProperties(a, destination); 
    BeanUtils.copyProperties(b, destination); 
    return destination; 
} 

전달

public static void nullAwareBeanCopy(Object dest, Object source) throws IllegalAccessException, InvocationTargetException { 
    new BeanUtilsBean() { 
     @Override 
     public void copyProperty(Object dest, String name, Object value) 
       throws IllegalAccessException, InvocationTargetException { 
      if(value != null) { 
       super.copyProperty(dest, name, value); 
      } 
     } 
    }.copyProperties(dest, source); 
} 

중첩 된 객체 솔루션

좀 더 강력한 솔루션입니다. 중첩 된 객체 복사를 지원합니다. 1+ 레벨 이상의 객체는 더 이상 참조로 복사되지 않습니다. 대신 중첩 된 객체가 복제되거나 해당 속성이 개별적으로 복사됩니다.

/** 
* Copies all properties from sources to destination, does not copy null values and any nested objects will attempted to be 
* either cloned or copied into the existing object. This is recursive. Should not cause any infinite recursion. 
* @param dest object to copy props into (will mutate) 
* @param sources 
* @param <T> dest 
* @return 
* @throws IllegalAccessException 
* @throws InvocationTargetException 
*/ 
public static <T> T copyProperties(T dest, Object... sources) throws IllegalAccessException, InvocationTargetException { 
    // to keep from any chance infinite recursion lets limit each object to 1 instance at a time in the stack 
    final List<Object> lookingAt = new ArrayList<>(); 

    BeanUtilsBean recursiveBeanUtils = new BeanUtilsBean() { 

     /** 
     * Check if the class name is an internal one 
     * @param name 
     * @return 
     */ 
     private boolean isInternal(String name) { 
      return name.startsWith("java.") || name.startsWith("javax.") 
        || name.startsWith("com.sun.") || name.startsWith("javax.") 
        || name.startsWith("oracle."); 
     } 

     /** 
     * Override to ensure that we dont end up in infinite recursion 
     * @param dest 
     * @param orig 
     * @throws IllegalAccessException 
     * @throws InvocationTargetException 
     */ 
     @Override 
     public void copyProperties(Object dest, Object orig) throws IllegalAccessException, InvocationTargetException { 
      try { 
       // if we have an object in our list, that means we hit some sort of recursion, stop here. 
       if(lookingAt.stream().anyMatch(o->o == dest)) { 
        return; // recursion detected 
       } 
       lookingAt.add(dest); 
       super.copyProperties(dest, orig); 
      } finally { 
       lookingAt.remove(dest); 
      } 
     } 

     @Override 
     public void copyProperty(Object dest, String name, Object value) 
       throws IllegalAccessException, InvocationTargetException { 
      // dont copy over null values 
      if (value != null) { 
       // attempt to check if the value is a pojo we can clone using nested calls 
       if(!value.getClass().isPrimitive() && !value.getClass().isSynthetic() && !isInternal(value.getClass().getName())) { 
        try { 
         Object prop = super.getPropertyUtils().getProperty(dest, name); 
         // get current value, if its null then clone the value and set that to the value 
         if(prop == null) { 
          super.setProperty(dest, name, super.cloneBean(value)); 
         } else { 
          // get the destination value and then recursively call 
          copyProperties(prop, value); 
         } 
        } catch (NoSuchMethodException e) { 
         return; 
        } catch (InstantiationException e) { 
         throw new RuntimeException("Nested property could not be cloned.", e); 
        } 
       } else { 
        super.copyProperty(dest, name, value); 
       } 
      } 
     } 
    }; 


    for(Object source : sources) { 
     recursiveBeanUtils.copyProperties(dest, source); 
    } 

    return dest; 
} 

다소 빠르고 더럽지 만 잘 작동합니다. 재귀를 사용하고 무한 재귀가 발생할 가능성이 있기 때문에 나는 안전에 놓이게됩니다.

+1

안녕하세요. 회신에 감사드립니다. 여기 BeanUtils.copyProperties (b, 대상)를 호출하면 무슨 일이 발생합니까? BeanUtils.copyProperties (a, destination)에 의해 카피 된 프로퍼티. 일부 속성에 대해 null 값을 가져 오는 중입니다. – user3860615

+0

@ user3860615 예전에이 문제가 발생하여 awnser가 업데이트되었습니다. –

+0

@ug_ nullAwareBeanCopy는 중첩 된 개체 병합을 지원하지 않는다고 생각합니다. – zt1983811

관련 문제