Unix 프로그램 diff와 유사한 Java 유틸리티 라이브러리가 있지만 Objects 용입니까? 동일한 유형의 두 개체를 비교하고 그 차이를 나타내는 데이터 구조를 생성 할 수있는 무언가를 찾고 있습니다 (그리고 인스턴스 변수의 차이를 재귀 적으로 비교할 수 있음). 난 하지 텍스트 DIFF의 자바 구현을 찾고. 리플렉션을 사용하여이 작업을 수행하는 방법에 대한 도움 도 찾고 있지 않습니다 .
내가 유지하고있는 애플리케이션은 디자인 선택이 좋지 않고 다시 작성해야하는이 기능의 취약한 구현을 가지고 있지만, 기성품을 사용할 수 있다면 더 좋을 것입니다.
내가 찾고있는 종류의 예는 다음과 같습니다.
SomeClass a = new SomeClass();
SomeClass b = new SomeClass();
a.setProp1("A");
a.setProp2("X");
b.setProp1("B");
b.setProp2("X");
DiffDataStructure diff = OffTheShelfUtility.diff(a, b); // magical recursive comparison happens here
비교 후 유틸리티는 “prop1″이 두 개체간에 다르고 “prop2″가 동일하다고 알려줍니다. DiffDataStructure가 트리가되는 것이 가장 자연스러운 일이라고 생각하지만 코드가 신뢰할 수 있다면 까다 롭지 않을 것입니다.
답변
조금 늦었을 수도 있지만, 저도 당신과 같은 상황에 있었고 결국 당신의 사용 사례에 맞는 저만의 라이브러리를 만들었습니다. 내가 직접 해결책을 찾아야했기 때문에 다른 사람들의 노력을 아끼기 위해 Github에 공개하기로 결정했습니다. 여기에서 찾을 수 있습니다 : https://github.com/SQiShER/java-object-diff
— 편집 —
다음은 OP 코드를 기반으로 한 약간의 사용 예입니다.
SomeClass a = new SomeClass();
SomeClass b = new SomeClass();
a.setProp1("A");
a.setProp2("X");
b.setProp1("B");
b.setProp2("X");
DiffNode diff = ObjectDifferBuilder.buildDefault().compare(a, b);
assert diff.hasChanges();
assert diff.childCount() == 1;
assert diff.getChild('prop1').getState() == DiffNode.State.CHANGED;
답변
http://javers.org 는 필요한 것을 정확히 수행하는 라이브러리입니다 : Diff 객체를 반환하는 compare (Object leftGraph, Object rightGraph)와 같은 메소드가 있습니다. Diff에는 변경 목록 (ReferenceChange, ValueChange, PropertyChange)이 포함됩니다.
given:
DummyUser user = dummyUser("id").withSex(FEMALE).build();
DummyUser user2 = dummyUser("id").withSex(MALE).build();
Javers javers = JaversTestBuilder.newInstance()
when:
Diff diff = javers.compare(user, user2)
then:
diff.changes.size() == 1
ValueChange change = diff.changes[0]
change.leftValue == FEMALE
change.rightValue == MALE
그래프의주기를 처리 할 수 있습니다.
또한 모든 그래프 개체의 스냅 샷을 얻을 수 있습니다. Javers에는 스냅 샷에 대한 JSON 직렬 변환기 및 역 직렬 변환기가 있으며 데이터베이스에 쉽게 저장할 수 있도록 변경됩니다. 이 라이브러리를 사용하면 감사를위한 모듈을 쉽게 구현할 수 있습니다.
답변
예, java-util 라이브러리에는 두 개의 Java Object Graph를 비교하는 GraphComparator 클래스가 있습니다. 차이를 델타 목록으로 반환합니다. GraphComparator를 사용하면 델타도 병합 (적용) 할 수 있습니다. 이 코드는 JDK에만 의존하고 다른 라이브러리에는 없습니다.
답변
Apache의 솔루션을 살펴볼 수도 있습니다. 대부분의 프로젝트는 commons-lang의 일부이기 때문에 이미 클래스 경로에 있습니다.
특정 필드의 차이점 확인 :
http://commons.apache.org/proper/commons-lang/javadocs/api-3.9/org/apache/commons/lang3/builder/DiffBuilder.html
리플렉션을 사용하여 차이점 확인 :
http://commons.apache.org/proper/commons-lang/javadocs/api-3.9/org/apache/commons/lang3/builder/ReflectionDiffBuilder.html
답변
모든 Javers 라이브러리는 Java 7 만 지원합니다. Java 6 프로젝트에 사용하기를 원했기 때문에 소스를 가져 와서 Java 6에서 작동하는 방식을 변경했습니다. 아래는 github 코드입니다. .
https://github.com/sand3sh/javers-forJava6
Jar 링크 : https://github.com/sand3sh/javers-forJava6/blob/master/build/javers-forjava6.jar
Java 7 지원 ‘<>’고유 캐스트 변환 만 Java 6 지원으로 변경했습니다. 모든 사용자 지정 개체 비교에서 작동하는 불필요한 코드를 거의 언급하지 않았기 때문에 모든 기능이 작동한다고 보장하지는 않습니다.
답변
이 코드를 사용하는 위치에 따라 유용하거나 문제가 될 수 있습니다. 이 코드를 테스트했습니다.
/**
* @param firstInstance
* @param secondInstance
*/
protected static void findMatchingValues(SomeClass firstInstance,
SomeClass secondInstance) {
try {
Class firstClass = firstInstance.getClass();
Method[] firstClassMethodsArr = firstClass.getMethods();
Class secondClass = firstInstance.getClass();
Method[] secondClassMethodsArr = secondClass.getMethods();
for (int i = 0; i < firstClassMethodsArr.length; i++) {
Method firstClassMethod = firstClassMethodsArr[i];
// target getter methods.
if(firstClassMethod.getName().startsWith("get")
&& ((firstClassMethod.getParameterTypes()).length == 0)
&& (!(firstClassMethod.getName().equals("getClass")))
){
Object firstValue;
firstValue = firstClassMethod.invoke(firstInstance, null);
logger.info(" Value "+firstValue+" Method "+firstClassMethod.getName());
for (int j = 0; j < secondClassMethodsArr.length; j++) {
Method secondClassMethod = secondClassMethodsArr[j];
if(secondClassMethod.getName().equals(firstClassMethod.getName())){
Object secondValue = secondClassMethod.invoke(secondInstance, null);
if(firstValue.equals(secondValue)){
logger.info(" Values do match! ");
}
}
}
}
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
답변
두 객체가 다른지 빠르게 알려주는 더 간단한 방법은 아파치 공용 라이브러리를 사용하는 것입니다.
BeanComparator lastNameComparator = new BeanComparator("lname");
logger.info(" Match "+bc.compare(firstInstance, secondInstance));