我很难创建关系的最佳 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 中映射关系两次。另一种方法是使其成为单向 OneToMany 关系,甚至不在 Friend 中明确指定 OWNER。这将为映射引入另一个表并使查询有点复杂。使用 ElementCollection 而不是 OneToMany 似乎很简单,但我的理解是我无法将 Friend 作为一个实体进行管理?
让我知道你们是否需要更多细节或要求。顺便说一句,我尝试将 MapsId 放入 PKEY 的 Owner 部分的 Friend 中,但这给了我运行时错误。
任何帮助表示赞赏。
注意:即使我向 Friend 添加生成的密钥,我也想强制 Friend 实体中 {owner,person} 组合的唯一性。