質問: JPAのエンティティクラスに、`equals`メソッドや`hashCode`メソッドは明示的に実装する必要がありますか? またその場合、主キーのみに基いて比較判定する処理であれば良いですか? それとも、`@Id`アノテーションがついているだけで良いですか? (JPAの内部で`@Id`付きフィールドを探して比較してくれる?) `@Embeddable`を付けた複合主キークラスは、`equals`と`hashCode`を実装しなければならない、ということは、以下サイトで知りましたが・・・ 関連しそうな情報を見つけましたが、英語が苦手なせいか、よく分かりませんでした:
回答: (既に正しいと私が考える回答は出ていますが、別の説明を試みてみます) 一般的なクラス設計の話として、Effective Java 第3版 第3章 項目10 "`equals` をオーバーライドするときは一般契約に従う" に次のように書かれています: > > `equals` メソッドをオーバーライドするのは簡単なように思えますが、間違ったやり方でオーバーライドしてしまう方法はたくさんあり、その結果は悲惨なものになります。問題を避ける最も簡単な方法は、`equals`メソッドをオーバーライドしないことです。 > > (中略) > > では、いつ `equals` をオーバーライドするのが適切でしょうか。それは、クラスが単なるオブジェクトの同一性とは異なる論理的等価性(logical equality)という概念を持っていて、かつスーパークラスが`equals`をオーバーライドしていないときです。 > > > JPAエンティティクラスはどうかというと、論理的等価性はあります(簡単にいうと`@Id`フィールドの値が同じであれば論理的に等価です(※十分条件であって必要条件ではない))。 ただし、JPAフレームワークは、論理的に等価であればデフォルト実装の`equals`も`true`になるよう(可能な限り)取り計らってくれますので、デフォルト実装で大抵の場合うまく動きます。 質問文に書かれているリンクより新しく具体的な説明がHibernateのユーザガイドにあります。 * 2.5.7. Implementing equals() and hashCode() - Hibernate ORM 5.4.4.Final User Guide > > Generally, this is pertinent for user-defined classes used as composite identifiers. Beyond this one very specific use case and few others we will discuss below, you may want to consider not implementing equals/hashCode altogether. > > > 質問文に対するそれぞれの回答としては: > > JPAのエンティティクラスに、equalsメソッドやhashCodeメソッドは明示的に実装する必要がありますか? > > > 通常は不要です。(原理主義的には実装するのが正しいですが、それより誤った実装を行ってしまうリスクを懸念すべきです。) > > またその場合、主キーのみに基いて比較判定する処理であれば良いですか? > > > (これは`equals`のオーバーライドが難しいことの1つの具体例ですが) 一般的にはこの考えは誤っています。 例えば `@Id` を `@GeneratedValue` で決定するJPAエンティティクラスは、永続化するまで主キーがありません。 > > それとも、@Idアノテーションがついているだけで良いですか? > > (JPAの内部で@Id付きフィールドを探して比較してくれる?) > > > 通常はその考えで良いです。 (同一Persistence Contextでは)同一`@Id`は同一インスタンスとなるよう取り計らってくれるので、`@Id`が同じなら `==` が`true`であり、すなわち`equals`が`true`になります。