1

見積もり検索画面の作成を担当しました。見積もりモデルを作成するために Oracle ビューを参照しました。ビュー テーブルには id 列がないため、私は quoteId.class を介して @IdClass アノテーションを使用して複合 ID を使用することを好みます。両方のモデルで hashCode と equals メソッドをオーバーライドします。quoteId equals & hashcode はすべてのフィールドの組み合わせを返し、quote hashcode & equals は単にモデルの this.quoteNo フィールドを比較するだけです。

引用モデル:

@Override
public int hashCode()
{
    return new HashCodeBuilder(17,37)
    .append(quoteNo)
    .toHashCode();
}

/*
 * (non-Javadoc)
 * 
 * @see java.lang.Object#equals(java.lang.Object)
 */
@Override
public boolean equals(Object obj)
{
    final quoteModel other = (quoteModel ) obj;
    return new EqualsBuilder().appendSuper(super.equals(other))
            .append(quoteNo, other.quoteNo).isEquals();
}

そして、ユニークなアイテムが必要なときは、次の方法でアクセスしていました:

uniqueQuoteResults = new ArrayList<Quote>(
                    new LinkedHashSet<Quote>(fullQuoteResults));

しかし、idClass の使用を開始すると、linkedHashSet にはすべてのアイテムが含まれており、引用番号も同じです。引用なしフィールド(比較可能、比較可能)を介して各アイテムの一意性を証明するための他の実装がありませんか?uniqueQuoteResult リスト項目の値をトレースすると、すべての項目の見積もり番号が同じになります。

編集注: Apache ライブラリの HashCodeBuilder と EqualsBuilder のサポートを使用する方法を変更しましたが、問題は変わりません。idClass ハッシュコードが linkedhashset に対して有効になっているのではないかと心配しています

4

1 に答える 1

2

モデル内の次のコードでテストするのは this.quoteNo で、obj.quoteNo と同じインスタンスです。

@Override
public boolean equals(Object obj)
{
    // TODO Auto-generated method stub
    return this.quoteNo == ((EprocAwquoteV) obj).quoteNo;
}

その結果、個別に構築された IdClass のインスタンスを持つ 2 つのインスタンスは、quoteNo が同じオブジェクトでない場合、等しくないと見なされます。代わりに、次のようなもので quoteNo の等価性をテストしたいと思います。

this.quoteNo.equals(other.quoteNo);

また、現在のモデルの equals の実装には、他にもいくつかの問題があります (たとえば、ClassCastException がスローされる可能性があります)。基本原則は、Object.equalsおよびOverriding the java equals() method quirkから見つけることができます。さらに、Hibernate では、同じクラスをテストするのではなく、代わりに instanceof を使用する必要があることを覚えておくことが重要です (プロキシ クラスのため)。エンティティに equals&hascode を記述する方法については、Hibernate のドキュメントを参照してください。

編集: 現在のアプローチは機能しません。

 return new EqualsBuilder().appendSuper(super.equals(other))

それを Object.equals に要約します。意味のある equals 実装を持つスーパークラスがない場合。あなたのケースを正しく理解しているかどうかは完全にはわかりません。そのため、次の実際の例を見て、違いがどこにあるかを確認してください。

public class QuoteId implements Serializable {
    private int id1;
    private int id2;

    public QuoteId() {}

    //This equals does not matter when we build LinkedHashSet
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        QuoteId other = (QuoteId) o;
        return id1 == other.id1 && id2 == other.id2;
    }

    public int hashCode() {
        return 31 * id1 + id2;
    }
}

@Entity
@IdClass(QuoteId.class)
public class Quote {
    @Id private int id1;
    @Id private int id2;
    String value;

    public Quote() {
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Quote other = (Quote) o;
        return id1 == other.id1 && id2 == other.id2;
    }

    @Override
    public int hashCode() { return 31 * id1 + id2;}

    //get&set for id1, id2, and value are omitted
}


tx.begin();
em.persist(new Quote(1, 1, "val"));
em.persist(new Quote(1, 2, "val"));
tx.commit();

TypedQuery<Quote> query = em.createQuery("SELECT q FROM Quote q", Quote.class);
List<Quote> twoQuotes = query.getResultList();//both

//duplicating (size=4) result for sake of test;
List<Quote> fullQuoteResults = new ArrayList<Quote>();
fullQuoteResults.addAll(twoQuotes);
fullQuoteResults.addAll(twoQuotes);

//will have same elements as in twoQuotes:
List<Quote> uniqueQuoteResults = new ArrayList<Quote>(
        new LinkedHashSet<Quote>(fullQuoteResults));
于 2012-03-11T18:37:57.003 に答える