2017-08-09 11 views
2

私はjava-object-diffを使用して、JAXBによってXMLから解析された2つのオブジェクトの違いを取得しています。以下の例では、同じ文字列を使用して違いがないかどうかを確認していますが、log.info("has changes: " + diff5.hasChanges());ログtrueです。オブジェクトが異なるhasChanges変更が検出されない

JAXBContext context1 = JAXBContext.newInstance(Item.class); 
Unmarshaller m1 = context1.createUnmarshaller(); 
Item base = (Item) m1.unmarshal(new StringReader(s)); 
Item working = (Item) m1.unmarshal(new StringReader(s)); 
DiffNode diff5 = ObjectDifferBuilder 
     .buildDefault() 
     .compare(working, base); 
log.info("has changes: " + diff5.hasChanges()); 
diff5.visit((node, visit) -> { 
    final Object baseValue = node.canonicalGet(base); 
    final Object workingValue = node.canonicalGet(working); 
    final String message = node.getPath() + " changed from " + 
      baseValue + " to " + workingValue; 
    System.out.println(message); 
}); 

私がするSystem.out.printlnから取得したメッセージは、これはすべてのプロパティのために起こることが<the actual value>nullから変更されていると言って、常に同じです。例えば。

content changed from null to Mit dem Wasserinonisator 

私は両方Itemsは、両方のactualyの同じ内容と全くを持っていることを確認したがnullが、まったく同じ内容ではありません。

Itemは多くのサブクラス(すべてのゲッターとセッターが存在する)であるpojoです。

java-object-diffを作成して値を正しく比較する方法はありますか?

+0

明らかに、 'node.canonicalGet(base)'は 'null'を返します。だから、 'DiffNode'と' ObjectDifferBuilder'の実装は何ですか? –

+0

コードで問題を再現しようとしましたが、別の動作が発生します。プログラムを実行すると、diff5.hasChanges()はfalseです。ソースコードを実行する際にソースコードを表示していることを再度確認してください。 –

+0

Ja、das ist auf jedenフォール・ジェネアップ・コード・デン・ベン・ベンツ。 Bringtのエスケープは、郵便配達と郵便配達を完了しましたか? @TobiasOtto – Michael

答えて

1

your codeをよく見ると、何が間違っているのか分かります。最初の問題は、JAXBがequalsメソッドを生成しないという事実です。 ObjectDifferは、階層に基づいてオブジェクト間の関係を確立できるため、ほとんどの場合、問題はありません。順序付けされていないか注文されていないときは、ObjectDifferはベースアイテムと作業インスタンスのコレクションアイテム間の関係を確立するための何らかの方法を必要とするため、複雑な作業が発生します(Collections)。デフォルトでは、基になるコレクションのルックアップメカニズムに依存している(通常はhashCodeequalsまたはcompareTo上または方法のより多く必要とする。)

をお使いの場合は特に、あなたのクラスのいずれも(しかしので、この関係は、確立できませんListsおよびSetsに含まれるもの)は、適切なequalsメソッドを実装します。これは、インスタンスは自分自身と一度も等しいことを意味します。責任クラスは値オブジェクトを表し、ハード識別子を持たないため、関係を簡単に確立することができます。したがって、唯一のオプションは、すべてのプロパティを単純に比較するカスタムequalsメソッドを提供することです。その結果、これらのオブジェクトのわずかな変更により、はベースバージョンをREMOVED、作業バージョンをADDEDとマークします。しかし、実際に変更されていないときにはCHANGEDとマークされません。それは何かです。問題のタイプについて、独自のde.danielbechler.diff.identity.IdentityStrategyを実装

  1. は、私はいくつかの代替ソリューションは、Javaオブジェクト・デフと考えられるので、ここで、それはJAXBがカスタムequalsメソッドを生成作ることがいかに簡単であるかわからないんだけどそのため(例は、Java 8つのラムダを使用する)ように、ObjectDifferBuilderにそれらを提供する:

    ObjectDifferBuilder 
        .startBuilding() 
        .identity() 
        .ofCollectionItems(ItemLinks.class, "itemLink").via((working, base) -> { 
        ItemLink workingItemLink = (ItemLink) working; 
        ItemLink baseItemLink = (ItemLink) base; 
        return StringUtils.equals(workingItemLink.getDescription(), baseItemLink.getDescription()) 
         && StringUtils.equals(workingItemLink.getURL(), baseItemLink.getURL()); 
        }) 
        // ... 
        .and().build(); 
    
  2. 比較時に問題の性質を無視します。明らかに、これはあなたが望むものではないかもしれませんが、特定のオブジェクトを本当に気にしない場合には、簡単な解決策です。

    ObjectDifferBuilder 
        .startBuilding() 
        .inclusion() 
        .exclude().type(Item.ImageSets.class) 
        .and().build(); 
    

JAXBは、カスタムを発生させるソリューションは方法が行くには私の好みの方法だろうと等しいです。私はanother postがそれが可能であると主張していることが分かったので、これを最初に試してみたいので、ObjectDifferをカスタマイズする必要はありません。

こちらがお役に立てば幸いです。

+0

ありがとうございます!だから、私はJAXBに適切なequalsメソッド(または最初の失敗の場合は私のIDE)を作成させ、それがうまくいくようにします。ニースプロジェクトbtw。 ! – Michael

関連する問題