外键作为主键或仅将代理主键与 JPA 上下文中的外键不同

Posted

技术标签:

【中文标题】外键作为主键或仅将代理主键与 JPA 上下文中的外键不同【英文标题】:Foreign key as the primary key or just separate surrogate primary key different from foreign key in JPA context 【发布时间】:2012-07-31 08:40:05 【问题描述】:

在 JPA 上下文中使用 FK 作为 PK 或使用代理 PK 和 FK 作为 FK 的最佳做法是什么? 我看到几次有人说他们必须将 FK 映射为 PK,因为他们有遗留数据库。那么这是否意味着对于新表,如果您可以控制创建它们,最好使用以下结构:

TABLE_1
-------
ID (PK)
...

TABLE_2
-------
ID (PK) 
TABLE_1_ID (FK)

代替:

TABLE_2
-------
TABLE_1_ID (PK) and (FK)

【问题讨论】:

【参考方案1】:

对于多对一关系,请始终使用您提出的第一个替代方案。

对于某些一对一的关系,可以合并表而不会产生不良影响。

第二个选择真正有用的地方是使用 class table inheritance model 实现超类-子类层次结构时,正如 Martin Fowler 所介绍的那样。在这种情况下,您希望保持子类表与超类表不同,以减少 NULL 的数量。但关系是一对一的。

通过使子类表中的 PK 和 FK 具有相同的键功能,并通过使 FK 引用超类表中的匹配条目,可以非常容易地将专用数据与通用数据连接起来,需要时。这可以称为“穷人的遗产”。

【讨论】:

【参考方案2】:

在这种特殊情况下(1 到 0..1 的关系),请考虑将两个表合并为一个。

如果它们被有意拆分(例如,对于“垂直”分区),则首选相同的字段同时作为 PK 和 FK。

只有在可以将其变小时才考虑添加另一个键1,但要平衡这与额外索引的需要2,对@987654321的潜在敌意@ 3 并且需要对菱形依赖关系进行建模4


1例如因为TABLE_2.TABLE_1_ID 是字符串,您可以将TABLE_2.ID 设为整数。

2每个新索引都会减慢 INSERT 的速度,并且可能会减慢 UPDATE 和 DELETE 的速度,具体取决于它们的 WHERE 子句。此外,任何额外的数据都会给缓存带来额外的压力,使其“更小”。

3聚簇表中的二级索引需要包含 PK 的副本,并且在定位行时会导致双重查找(首先是索引,然后是 PK)。 em>

4可能需要在“钻石”的两个“边缘”上使用识别关系,以确保钻石的“底部”引用单个 “顶”。

【讨论】:

【参考方案3】:

我猜你正在寻找@MapsId 注释。

【讨论】:

以上是关于外键作为主键或仅将代理主键与 JPA 上下文中的外键不同的主要内容,如果未能解决你的问题,请参考以下文章

外键为啥必须是唯一键?为啥至少唯一键才能作为其他表的外键?不唯一为啥不可以?

联结表将包含单个表的外键或主键

如何使用主键作为JPA和Hibernate的外键引用?

如何分清SQL数据库中的主键与外键

MyBatis - 关联查询

在navicat中怎么外键与主键关联