リレーションシップの最適な JPA 表現を作成するのに苦労しています。いろいろな方法があるようで、どれが最適なのかわかりません。JPA がなければ、構造を PERSON テーブルと FRIEND テーブルとして表すことができます。PERSON テーブルに ID と NAME だけがあるとします。FRIEND テーブルには、OWNER_ID、PERSON_ID、および設定可能なブール値の IS_ACTIVE フィールドがあります。OWNER_ID と PERSON_ID はどちらも PERSON テーブルを参照します。人は多くの友達を持つことができるので、一意の主キーは OWNER_ID と PERSON_ID になります。私のコードでは、PersonEntity で関係を制御したいと考えています。Java での操作は次のようになります。
person1.getFriends().add( new Friend( person2, isActive ) );
Friend friend = person1.findFriend( person2ID );
そんな感じ。JPA にフレンド関係の OWNER を暗黙的に割り当ててもらいたいことに注意してください。上記のコードでは、Friend コンストラクターには渡さず、複合キーの PERSON 部分のみを渡します。
これが私の最初の推測でした:
@Entity
public class Person {
@Id
@GeneratedValue
private Long id;
@OneToMany( mappedBy="key.owner", cascade=CascadeType.ALL, orphanRemoval = true)
private Set<Friend> friends = new HashSet<>();
// getter and setter for Friends
...
}
@Entity
public class Friend {
@EmbeddedId
private Key key = new Key();
private boolean isActive;
...
@Embeddable
public static class Key implements Serializable {
@ManyToOne
private Person owner;
@OneToOne
private Person person;
...
}
}
しかし、このコードを使用すると、スタック オーバーフロー エラーが発生します。OneToOneの関係で混乱していると思います。
JPA 2.0でこの種の関係をモデル化する最良の方法は何ですか? 最も簡単なのは、生成された長いキーを Friend に導入することだと思います。しかし、「ジョンの友達を見つける」のクエリがより複雑になるようです。これは、基本的に SQL で関係を 2 回マッピングする 3 番目のマッピング テーブルを導入するためです。もう 1 つの方法は、一方向の OneToMany 関係にし、Friend で明示的に OWNER を指定することさえしないことです。これにより、マッピング用に別のテーブルが導入され、クエリが少し複雑になります。OneToMany の代わりに ElementCollection を使用するのは簡単に思えますが、私の理解では、Friend をエンティティとして管理できませんでした。
詳細や要件が必要な場合はお知らせください。ところで、PKEY の所有者部分の Friend に MapsId を入れようとしましたが、実行時エラーが発生しました。
どんな助けでも大歓迎です。
注: 生成されたキーを Friend に追加しても、Friend エンティティの {owner,person} の組み合わせに一意性を適用したいと考えています。