2012-12-24 8 views
10

JavaでUDTの実装を#equalsにすると、渡された引数オブジェクトは現在のクラスのインスタンスでなければなりません。そうでない場合は失敗します。return falseEffective Java(EJ2) 。しかし、Hibernate 4を使用している間に、この#equalsの条件が失敗する遅延ロードのために、javassistプロキシインスタンスで終わる可能性があります。これを克服するための最良の選択は何でしょうか?私が考えることのできるいくつかの選択肢は:Hibernate javassistのプロキシと `Object#equals`

  • の実装を拡張して、プロキシのケースを考慮に入れてください。短所:Hibernateプロキシインフラストラクチャ、ハッキー、エンティティまたはドメインモデルへの保守性の高い料金、ハードワイヤード依存性は、使用されているORMには、ORMを必要としない異なるコンテキストで再利用される可能性があるため、スイングUI。
  • equalsを呼び出す前にプロキシであるかどうかを確認してください。短所:常に可能なわけではない、すなわち、コレクションおよび暗黙的な呼び出しの処理equals、たとえば、マップ。
  • 遅延読み込みを使用しないようにします。短所:すべてのユースケースで合理的でも効率的でもない。コメントの一つに指摘したよう

UPDATE

再び、私は次のようにすべてのシナリオ(タイプ型、型プロキシ、プロキシ型およびプロキシプロキシ)のために働くだろうと信じていEJ2の確認が、タイプが完全に異なるタイプと比較される場合、それは永遠にループします。 Person.equals(Employee)であり、どちらもEJ2基準に等しい。 1.イコールで使用するように変更instanceofは代わりのクラスの平等:

if (this.getClass() != anObject.getClass()) 
    { 
     return anObject.equals(this); 
    } 
+0

プロキシはエンティティのクラスを拡張しますか? –

+0

プロキシインスタンスは拡張されません。 'InvocationHandler'と'(this.getClass()== anObject.getClass()) 'の条件は勿論falseに評価されます。 –

+1

オプションを廃止しました。有効なJavaアドバイスを無視し、.equals()内のサブクラスを許可しました。 –

答えて

9

私は同じ問題につまずきました。私が修正したのは、.equalsの方法を変更することでした。

@Override 
public boolean equals(Object obj) { 
    if (this == obj) 
     return true; 
    if (obj == null) 
     return false; 
    if (!getClass().isAssignableFrom(obj.getClass())) 
     return false; 
    AbstractEntity other = (AbstractEntity) obj; 
    if (getId() == null) { 
     if (other.getId() != null) 
      return false; 
    } else if (!getId().equals(other.getId())) 
     return false; 
    return true; 

トリックが同じになるようにクラスを比較するが、isAssignableFrom -methodを使用しないことです。もう1つのトリックは、直接プロパティ(other.id)を使用しないで、取得メソッドを使用することです(other.getId()

+0

getClass()。isAssignableFrom(obj.getClass())は常にfalseを返します –

+0

これは私のためのトリックでした。それをテストする方法です:Employee employeeRef = em.getReference(Employee.class、id); Employee employee = em.find(Employee.class、id); Asser t.assertTrue(employee.equals(employeeRef)); –

+0

最初の行にStackOverflowエラーが表示されます – pozuelog

1

あなたは2つのことを行うことができます。プロキシのタイプはエンティティのタイプと同じではなく、むしろエンティティのタイプを拡張します。

  1. アンラップ実体そのものを取得するためのプロキシ(あなたがそれを行うことができますいくつかの休止状態のツールがあります)
+0

プロキシは拡張されないので、これは機能しません。 – Nicktar

6

私はWillem de Witの答えにコメントする評判はありません。私は新しい答えを投稿する必要があります。 djechelonの問題を解決するために

、あなたはこの行置き換える必要があります。そして、あなたはイコールはすべてのシナリオ(タイプタイプ、タイプのために働くことを保証します

if (!obj.getClass().isAssignableFrom(getClass()) && !getClass().isAssignableFrom(obj.getClass())) 

ため

if (!getClass().isAssignableFrom(obj.getClass())) 

をプロキシ、プロキシタイプ、プロキシプロキシ)。

私もあなたの答えを投票するという評判はありません。私はとても悲惨です!(休止状態を使用して)

1

上記DHansenによって答えは近いですが、私にとっては、この問題を解決:

if (!Hibernate.getClass(this).equals(Hibernate.getClass(obj))) { return false; } Dr. Hans-Peter Störr

によって示唆されているようにもそれは常に使用「ゲッター」に重要ですウィレム・デ・ウィット(Willem de Wit)の上記のように。