【问题标题】:JPA - Compound key vs generated id in Many to many tableJPA - 多对多表中的复合键与生成的 id
【发布时间】:2014-08-16 06:32:13
【问题描述】:

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

@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) 阅读了有关唯一索引的信息,但我不知道这是否是解决该问题的正确方法。

【问题讨论】:

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


    【解决方案1】:

    1.我建议使用代理键。我发现将记录的数据库身份与其业务身份分开会很有帮助。如果这两个概念混合在一起,那么对它们进行正确建模并在以后对其进行重构可能会很麻烦。您参考了一些很好的答案,因此您可能知道主要的优点和缺点,无需在此重申。另外一点是,您可以依靠UUID 之类的代理键来正确实现equalshashCode。为复合键实现这些以很好地与集合和数据库一起使用可能会很棘手。

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

    2. AFAIK,在 EmbeddedIdIdClass 之间做出选择主要是个人喜好问题。我更喜欢 IdClass,因为它避免了在查询 id 属性时必须添加导航:

    ... WHERE a.id.attribute = :attEmbeddedId 对比

    ... WHERE a.attribute = :attIdClass 对比

    我认为您链接 6 的论点没有说服力。复合键往往由实体的最具特征的属性组成。因为它们恰好被用作 DB 键而将它们隐藏在不同的类中对我来说似乎很尴尬。

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

    如果您尚未使用 JPA 2.1,您可能希望使用唯一约束,例如 explained here

    【讨论】:

    • 非常感谢 kostja 的详细回答。
    猜你喜欢
    • 2013-02-08
    • 2015-12-13
    • 2015-09-30
    • 2020-11-15
    • 1970-01-01
    • 1970-01-01
    • 2020-03-03
    • 2012-09-28
    • 2011-01-23
    相关资源
    最近更新 更多