があったいくつかの 議論ここでは、JPA エンティティと、JPA エンティティ クラスに使用する実装についてhashCode()
説明equals()
します。それらのほとんど (すべてではないにしても) は Hibernate に依存していますが、JPA 実装に依存しない形で説明したいと思います (ちなみに、私は EclipseLink を使用しています)。
すべての可能な実装には、次の点に関してそれぞれ長所と短所があります。
hashCode()
/equals()
操作の契約適合性(不変性)List
Set
- 同一のオブジェクト(異なるセッション、遅延ロードされたデータ構造からの動的プロキシなど)を検出できるかどうか
- エンティティが分離(または非永続)状態で正しく動作するかどうか
私の知る限り、3つの選択肢があります:
- それらを無視せず、頼りにし
Object.equals()
てObject.hashCode()
hashCode()
/equals()
仕事- 同一のオブジェクトを識別できない、動的プロキシの問題
- 分離されたエンティティには問題はありません
- 主キーに基づいて上書きする
hashCode()
/equals()
壊れています- 正しい ID (すべての管理対象エンティティ)
- 分離されたエンティティの問題
- Business-Idに基づいてそれらを上書きします(非主キー フィールド。外部キーはどうでしょうか?)
hashCode()
/equals()
壊れています- 正しい ID (すべての管理対象エンティティ)
- 分離されたエンティティには問題はありません
私の質問は次のとおりです:
- オプションや賛否両論を見逃したのでしょうか?
- どのオプションを選択しましたか? またその理由は何ですか?
更新1:
「hashCode()
/equals()
が壊れている」とは、連続したhashCode()
呼び出しで異なる値が返される可能性があることを意味します。これは、(正しく実装されている場合) API ドキュメントの意味では壊れていませんが、 、またはその他のハッシュベースObject
の から変更されたエンティティを取得しようとすると問題が発生します。その結果、JPA 実装 (少なくとも EclipseLink) は、場合によっては正しく動作しません。Map
Set
Collection
更新2:
ご回答ありがとうございます。ほとんどの回答は素晴らしい質です。
残念ながら、実際のアプリケーションに最適なアプローチはどれか、また自分のアプリケーションに最適なアプローチをどのように決定すればよいか、まだよくわかりません。そのため、この質問はそのままにして、さらに議論や意見をいただければと思います。
ベストアンサー1
このテーマに関する非常に素晴らしい記事を読んでください:Hibernate に個人情報を盗まれないように。
記事の結論は次のようになります。
オブジェクトがデータベースに永続化されている場合、オブジェクト ID を正しく実装するのは意外に難しいです。しかし、問題は、オブジェクトが保存される前に ID なしで存在できるようにすることから生じます。Hibernate などのオブジェクト リレーショナル マッピング フレームワークからオブジェクト ID の割り当ての責任を取り除くことで、これらの問題を解決できます。代わりに、オブジェクトがインスタンス化されるとすぐにオブジェクト ID を割り当てることができます。これにより、オブジェクト ID がシンプルでエラーがなくなり、ドメイン モデルに必要なコードの量も減ります。