JPA - 复合键与多对多表中生成的id

时间:2014-06-25 15:38:07

标签: jpa many-to-many unique-index surrogate-key compound-key

我正在创建一种社交网络,我的用户可以关注其他用户。所以我有一个像:

这样的实体
@Entity
public class FollowedUser{
    @ManyToOne
    private User user;

    @ManyToOne
    private User followedUser;

    //more fields

    ...
}

我不能拥有ManyToMany关系,因为我的FollowedUser实体中有更多字段。现在,我的问题是:

  1. 我应该使用复合密钥还是生成的ID(代理密钥)?我已阅读以下链接(123)关于建议代理密钥的主题,但我不知道它们是否适用于我的具体案例(其中)我的复合键将由两个代理外键组成)。此处(4)它表示“复合主键通常在从旧数据库映射时出现”,所以我认为不鼓励它们。
  2. 如果我应该使用复合键,我不知道是否应该使用@IdClass(这里推荐5)或@EmbeddedId(这里推荐6)或任何其他选项。虽然我认为没关系。
  3. 如果我应该使用代理键,我不知道如何仍然无法重复复合候选键。我在这里读过(7)有关唯一索引但我不知道这是否是解决该问题的正确方法。

1 个答案:

答案 0 :(得分:1)

1。我建议使用代理键。我发现将记录的数据库标识与其业务标识分开是有帮助的。如果这两个概念是混合的,那么对它们进行正确建模并稍后重新构造它们可能很麻烦。你引用了一些很好的答案,所以你可能已经意识到了主要的上行和下行,这里不需要重复它们。还有一点是,您可以依赖UUID这样的代理键来正确实施equalshashCode。实现复合键的那些可以很好地兼顾集合和数据库,这可能很棘手。

对于您的用例,用户之间的连接可以被视为自己的实体,并具有自动生成的代理PK。您可以在数据库中强制实施业务键属性的唯一性,请参阅第3页。

2。 AFAIK,在EmbeddedIdIdClass之间做出决定主要是品味问题。我更喜欢 IdClass,因为它可以避免在查询id属性时添加导航:

... WHERE a.id.attribute = :attEmbeddedId vs。

... WHERE a.attribute = :attIdClass

我没有发现你链接的论点6令人信服。复合键往往由实体的最具特征的属性组成。要将它们隐藏在另一个类中,因为它们碰巧被用作数据库密钥对我来说似乎很尴尬。

3。唯一索引看起来是保证属性组合唯一性的好方法。您可能需要阅读this answers, there is a small example

如果您尚未使用JPA 2.1,则可能需要使用唯一约束,explained here