2012-02-13 5 views
3

私は休止状態を使用しており、双方向の関係を持っています。両方のクラスでequals()を正しくオーバーライドする方法(PS:これは、エンティティの悪い例と選択肢ですが、私はそれについて移動する推奨方法を学ぶことに興味を持っています)cyclic equals()の結果がstackoverflowになる

ここ

は、コード(グアバ・オブジェクトを使用して)です。

@Entity 
@Table(name = "DESTINATION") 
public class Destination{ 
    private Integer id; 
    private String name; 
    private Set<DestinationAlias> aliases = new HashSet<DestinationAlias>(0); 


    @Override 
    public boolean equals(Object obj) { 
     if(obj == this) return true; 

     if(obj instanceof Destination){ 
      final Destination otherDestination = (Destination) obj; 
      return Objects.equal(getName().toUpperCase(), otherDestination.getName().toUpperCase()) 
        && Objects.equal(getAliases(), otherDestination.getAliases()); 
     } 
     return false; 
    } 
} 

DestinationAlias

@Entity 
@Table(name = "DESTINATIONALIAS") 
public final class DestinationAlias { 
    private Integer idDestinationAlias; 
    private String alias; 
    private Destination mainCity; 

    @Override 
    public boolean equals(Object obj) { 
     if(obj == this) return true; 

     if(obj instanceof DestinationAlias){ 
      final DestinationAlias otherAlias = (DestinationAlias) obj; 
      return Objects.equal(getAlias().toUpperCase(), otherAlias.getAlias().toUpperCase()) 
        && Objects.equal(getMainCity(), otherAlias.getMainCity()); 
     } 
     return false; 
    } 
} 

これはテストcでありますase:

@Test 
public void testEqualsto(){ 
    Destination dest = new Destination("abc", 1.0f, 1.0f); 
    dest.getAliases().add(new DestinationAlias("abc alias", dest)); 

    Destination dest1 = new Destination("abc", 1.0f, 1.0f); 
    dest1.getAliases().add(new DestinationAlias("abc alias", dest1)); 

    assertEquals(dest, dest1); 
} 

これは、equals()が交互に他のequals()を呼び出すため、サイクルが発生するため、期待通りにスタックオーバーフローが発生します。

双方向エンティティに対してequals()をオーバーライドするには、どのような方法が推奨されますか。

答えて

3

手動で解除する必要があります。それだけでDestionationのIDを比較するようにDestinationAliasで、私は(彼らは一意である必要があります)equals式を変更したい:

return Objects.equal(getAlias().toUpperCase(), otherAlias.getAlias().toUpperCase()) 
      && Objects.equal(getMainCity().getId(), otherAlias.getMainCity().getId()); 
              ^^^^^^^^       ^^^^^^^^ 

さらに、

+0

を読むが、私はdestinationIDを使用して、データベース上のプライマリキーにマップされることで、宛先を一意に識別しています。 (プロキシ・オブジェクトの場合はNULLになる可能性があります) – brainydexter

+0

理想的には、指定された作業単位で同じIDを持つエンティティーのインスタンスを1つだけ持つことが理想的です。あなたは 'if(obj == this)'ショートカットに頼ることができ、無限再帰はこの制約が違反していることを示します。 – millimoose

+0

@Inerdialあなたはその声明で少し詳しく説明できますか? – brainydexter