2011-05-23 12 views
16

के लिए दो जावा बीन्स के बीच मतभेदों का पता लगाएं कि मेरे पास एक जावा बीन/100 फ़ील्ड वाली इकाई है (विरासत में है या यह इस मामले में प्रासंगिक नहीं है)। अद्यतन संचालन के बाद - एक लेनदेन में, मैं यह निर्धारित करना चाहता हूं कि सीवीएस जैसे अपडेट ट्रैक करने के लिए कौन से फ़ील्ड संशोधित किए गए हैं। ऐसा करने का सबसे आसान तरीका क्या है? कोई फ्रेमवर्क सुझाव? क्या मुझे इस वस्तु के दो उदाहरण बनाना चाहिए और सभी क्षेत्रों में पुनरावृत्ति करना चाहिए और फ़ील्ड के मूल्यों से मेल खाना चाहिए? ऐसी परिस्थितियों में सर्वोत्तम बराबर विधि कैसे दिखाई देगी? निम्नलिखित बराबर() बहुत ही अजीब लगता है:संस्करण ट्रैकिंग

return (field1.equals(o.field1)) && 
(field2.equals(o.field2)) && 
(field3.equals(o.field3)) && 
... 
(field100.equals(o.field100)); 

उत्तर

29

आप अपाचे कॉमन्स बीनटिल का उपयोग कर सकते हैं। - लेखा परीक्षा और diff ढांचे वस्तुओं

package at.percom.temp.zztests; 

import java.lang.reflect.InvocationTargetException; 
import org.apache.commons.beanutils.BeanMap; 
import org.apache.commons.beanutils.PropertyUtilsBean; 
import java.util.Arrays; 
import java.util.HashSet; 
import java.util.Objects; 
import java.util.Set; 

public class Main { 

    public static void main(String[] args) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { 
     Main main = new Main(); 
     main.start(); 
    } 

    public void start() throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { 
     SampleBean oldSample = new SampleBean("John", "Doe", 1971); 
     SampleBean newSample = new SampleBean("John X.", "Doe", 1971); 

     SampleBean diffSample = (SampleBean) compareObjects(oldSample, newSample, new HashSet<>(Arrays.asList("lastName")), 10L); 
    } 

public Object compareObjects(Object oldObject, Object newObject, Set<String> propertyNamesToAvoid, Long deep) { 
    return compareObjects(oldObject, newObject, propertyNamesToAvoid, deep, null); 
} 

private Object compareObjects(Object oldObject, Object newObject, Set<String> propertyNamesToAvoid, Long deep, 
     String parentPropertyPath) { 
    propertyNamesToAvoid = propertyNamesToAvoid != null ? propertyNamesToAvoid : new HashSet<>(); 
    parentPropertyPath = parentPropertyPath != null ? parentPropertyPath : ""; 

    Object diffObject = null; 
    try { 
     diffObject = oldObject.getClass().newInstance(); 
    } catch (Exception e) { 
     return diffObject; 
    } 

    BeanMap map = new BeanMap(oldObject); 

    PropertyUtilsBean propUtils = new PropertyUtilsBean(); 

    for (Object propNameObject : map.keySet()) { 
     String propertyName = (String) propNameObject; 
     String propertyPath = parentPropertyPath + propertyName; 

     if (!propUtils.isWriteable(diffObject, propertyName) || !propUtils.isReadable(newObject, propertyName) 
       || propertyNamesToAvoid.contains(propertyPath)) { 
      continue; 
     } 

     Object property1 = null; 
     try { 
      property1 = propUtils.getProperty(oldObject, propertyName); 
     } catch (Exception e) { 
     } 
     Object property2 = null; 
     try { 
      property2 = propUtils.getProperty(newObject, propertyName); 
     } catch (Exception e) { 
     } 
     try { 
      if (property1 != null && property2 != null && property1.getClass().getName().startsWith("com.racing.company") 
        && (deep == null || deep > 0)) { 
       Object diffProperty = compareObjects(property1, property2, propertyNamesToAvoid, 
         deep != null ? deep - 1 : null, propertyPath + "."); 
       propUtils.setProperty(diffObject, propertyName, diffProperty); 
      } else { 
       if (!Objects.deepEquals(property1, property2)) { 
        propUtils.setProperty(diffObject, propertyName, property2); 
        System.out.println("> " + propertyPath + " is different (oldValue=\"" + property1 + "\", newValue=\"" 
          + property2 + "\")"); 
       } else { 
        System.out.println(" " + propertyPath + " is equal"); 
       } 
      } 
     } catch (Exception e) { 
     } 
    } 

    return diffObject; 
} 

    public class SampleBean { 

     public String firstName; 
     public String lastName; 
     public int yearOfBirth; 

     public SampleBean(String firstName, String lastName, int yearOfBirth) { 
      this.firstName = firstName; 
      this.lastName = lastName; 
      this.yearOfBirth = yearOfBirth; 
     } 

     public String getFirstName() { 
      return firstName; 
     } 

     public String getLastName() { 
      return lastName; 
     } 

     public int getYearOfBirth() { 
      return yearOfBirth; 
     } 
    } 
} 
+2

यदि आपका खाता 1 का शून्य शून्य है तो आपका कोड NullPointerException के साथ समाप्त हो सकता है। –

+1

बेशक सुधार के लिए बहुत सी जगह है, इसे अवधारणा के सबूत के रूप में समझा जाना चाहिए - उत्पादन-तैयार कोड के रूप में नहीं। इसके अलावा अगर कोई पुराना ऑब्जेक्ट और न्यू ऑब्जेक्ट मेल नहीं खाता है तो बहुत ही अपवाद हो सकता है ... – t3chris

+0

दुर्भाग्यवश यह जटिल वस्तुओं के लिए काम नहीं करता है :-( – rodrigocprates

1

आप गुण चेकआउट करने के लिए अपाचे BeanUtils उपयोग कर सकते हैं।

+0

BeanUtils का जो पैकेज मुझे जानकारी देता है जो संपत्ति बदला गया? –

+0

मेरा मतलब था कि आप गुण सरणी के माध्यम से पुनरावृत्त कर सकते हैं, जिसे बीनयूटल्स द्वारा वापस किया जाता है और मूल्यों की जांच करता है। –

5

आप फ़ील्ड लोड करने के लिए प्रतिबिंब का उपयोग कर सकते हैं और फिर उन्हें प्रत्येक ऑब्जेक्ट पर आमंत्रित कर सकते हैं और परिणाम की तुलना कर सकते हैं।

उदाहरण स्रोत कोड इस प्रकार दिखाई देंगे:

public static <T> void Compare(T source, T target) throws IllegalArgumentException, IllegalAccessException { 

      if(source == null) { 
       throw new IllegalArgumentException("Null argument not excepted at this point"); 
      } 

      Field[] fields = source.getClass().getFields(); 

      Object sourceObject; 
      Object targetObject; 

      for(Field field : fields){ 
       sourceObject = field.get(source); 
       targetObject = field.get(target); 

       //Compare the object 

      } 

     } 

FYI करें, इस कोड को सार्वजनिक क्षेत्रों वर्ग के लिए घोषित पर केवल काम करेंगे।

+2

ध्यान दें कि आप हमेशा सेट अप करने योग्य (सत्य) के साथ सार्वजनिक क्षेत्र की सीमा के आसपास हो सकते हैं; – TheLQ

14

अरे Javers पर यह वास्तव में आप क्या जरूरत है देखो: यहाँ एक सरल उदाहरण है। जावर के साथ आप अपने डोमेन ऑब्जेक्ट्स पर प्रत्येक अपडेट के बाद एक javers.commit() कॉल के साथ किए गए परिवर्तनों को जारी रख सकते हैं। जब आप कुछ बदलावों को जारी रखते हैं तो आप उन्हें आसानी से javers.getChangeHistory तक पढ़ सकते हैं, उदा।

public static void main(String... args) { 
    //get Javers instance 
    Javers javers = JaversBuilder.javers().build(); 

    //create java bean 
    User user = new User(1, "John"); 

    //commit current state 
    javers.commit("author", user); 

    //update operation 
    user.setUserName("David"); 

    //commit change 
    javers.commit("author", user); 

    //read 100 last changes 
    List<Change> changes = javers.getChangeHistory(instanceId(1, User.class), 100); 

    //print change log 
    System.out.printf(javers.processChangeList(changes, new SimpleTextChangeLog())); 
} 

और आउटपुट है:

commit 2.0, author:author, 2015-01-07 23:00:10 
    changed object: org.javers.demo.User/1 
    value changed on 'userName' property: 'John' -> 'David' 
commit 1.0, author:author, 2015-01-07 23:00:10 
    new object: 'org.javers.demo.User/1 
संबंधित मुद्दे