5.3. equals() と hashCode() の実装
以下の場合、
equals() メソッドと hashCode() メソッドをオーバーライドしなければなりません。
- 永続クラスのインスタンスを
Setに置く場合 (多値関連を表すのに推奨される方法です)。 同時に - 分離インスタンスをセッションへ再追加する場合。
Hibernate は、永続 ID (データベースの行) と、 特定のセッション範囲内の Java ID のみ等価性を保証します。 異なるセッションで読み出されたインスタンスを混合する場合、
Set に意味のあるセマンティクスを持たせるためには equals() と hashCode() を実装しなければなりません。
両方のオブジェクトの識別子値を比較して
equals()/hashCode() を実装する方法が最も明白な方法です。値が同じ場合、 両方が同じデータベース行になります。 両方が Set に追加されると、 Set には 1 つの要素のみが存在することになります。残念ながらこの方法は生成された識別子には使用できません。 Hibernate は永続化されたオブジェクトへのみ識別子の値を割り当てます。 新たに作成されたインスタンスには識別子の値がありません。また、 インスタンスが保存されていない状態で現在 Set にある場合、 保存するとオブジェクトに識別子の値が割り当てられます。 equals() と hashCode() が識別子の値を基にしている場合、 ハッシュコードが変更になり Set のコントラクトに違反することがあります。 この問題の詳細については、 Hibernate の Web サイトを参照してください。これは Hibernate の問題ではなく、オブジェクト識別と等価といった通常の Java セマンティックの問題になります。
ビジネスキーの等価性 を使用して、
equals() と hashCode() を実装することが推奨されます。 ビジネスキーの等価性とは、 equals() メソッドがビジネスキーを構成するプロパティのみを比較することを意味します。 現実のインスタンスを識別するキーになります (自然な候補キー)。
ビジネスキーはデータベースの主キー候補ほど安定性は必要ありません (「オブジェクト識別子の考察」 を参照してください)。 通常、 不変のプロパティや固有のプロパティがビジネスキーに適切な候補となります。