JPA:@JoinColumn 和 @PrimaryKeyJoinColumn 之间的区别?

Posted

技术标签:

【中文标题】JPA:@JoinColumn 和 @PrimaryKeyJoinColumn 之间的区别?【英文标题】:JPA: difference between @JoinColumn and @PrimaryKeyJoinColumn? 【发布时间】:2011-03-25 22:20:03 【问题描述】:

@JoinColumn@PrimaryKeyJoinColumn 之间的确切区别是什么?

您将@JoinColumn 用于作为外键一部分的列。典型的列可能如下所示(例如,在具有附加属性的连接表中):

@ManyToOne
@JoinColumn(name = "...")
private OtherClass oc;

如果我也将该列提升为 PK(也称为识别关系),会发生什么情况?由于该列现在是PK,我必须用@Id标记它:

@Id
@ManyToOne
@JoinColumn(name = "...")
private OtherClass oc;

现在的问题是:

@Id + @JoinColumn@PrimaryKeyJoinColumn 一样吗?:

@ManyToOne
@PrimaryKeyJoinColumn(name = "...")
private OtherClass oc;

如果不是,那@PrimaryKeyJoinColumn 是干什么用的?

【问题讨论】:

【参考方案1】:

如果我也将该列提升为 PK(也称为识别关系),会发生什么情况?由于该列现在是 PK,我必须用 @Id (...) 标记它。

这种对派生标识符的增强支持实际上是new stuff in JPA 2.0 的一部分(请参阅JPA 2.0 规范中的2.4.1 与派生标识符对应的主键部分) , JPA 1.0 不允许在 OneToOneManyToOne 上使用 Id。使用 JPA 1.0,您必须使用 PrimaryKeyJoinColumn 并为外键列定义 Basic Id 映射。

现在的问题是:@Id + @JoinColumn 和 @PrimaryKeyJoinColumn 一样吗?

您可以获得类似的结果,但在OneToOneManyToOne 上使用Id简单得多,并且是使用 JPA 2.0 映射派生标识符的首选方法。 PrimaryKeyJoinColumn 可能仍用于 JOINED 继承策略。在 JPA 2.0 规范的相关部分下方:

11.1.40 PrimaryKeyJoinColumn 注解

PrimaryKeyJoinColumn 注释 指定一个主键列 用作外键加入 另一个表。

PrimaryKeyJoinColumn 注释 用于连接主表 JOINED 中的实体子类 映射到主表的策略 它的超类;它在一个内使用 SecondaryTable注解加入一个 从表到主表; 它可以用于OneToOne 映射其中的主键 引用实体用作 被引用的外键 实体[108].

...

如果没有PrimaryKeyJoinColumn 为子类指定注释 在JOINED映射策略中, 外键列假定为 与主键同名 主表的列 超类。

...

示例: Customer 和 ValuedCustomer 子类

@Entity
@Table(name="CUST")
@Inheritance(strategy=JOINED)
@DiscriminatorValue("CUST")
public class Customer  ... 

@Entity
@Table(name="VCUST")
@DiscriminatorValue("VCUST")
@PrimaryKeyJoinColumn(name="CUST_ID")
public class ValuedCustomer extends Customer  ... 

[108] 派生的id机制 现在在第 2.4.1.1 节中描述 优先于 PrimaryKeyJoinColumn 为 OneToOne 映射案例。

另见

Primary Keys through OneToOne Relationships

此来源http://weblogs.java.net/blog/felipegaucho/archive/2009/10/24/jpa-join-table-additional-state 声明使用@ManyToOne 和@Id 可用于JPA 1.x。现在谁是正确的?

作者正在使用 EclipseLink 的预发布 JPA 2.0 兼容版本(发文时版本为 2.0.0-M7)来撰写有关 JPA 1.0(!) 的文章。这篇文章具有误导性,作者使用的东西不是 JPA 1.0 的一部分。

作为记录,EclipseLink 1.1 中添加了对 OneToOneManyToOne 的支持(参见 this message 来自 James Sutherland,EclipseLink 提交者和 Java Persistence 维基书的主要贡献者)。但让我坚持,这不是 JPA 1.0 的一部分。

【讨论】:

此来源 weblogs.java.net/blog/felipegaucho/archive/2009/10/24/… 声明使用 @ManyToOne 和 @Id 可用于 JPA 1.x。现在谁是对的? 好的。感谢您清除它。我是对的,a 提到的坏例子错误地使用了@IdClass? @Id 注释不应该放在实体类中的单独(冗余/重复)列中正确吗? (尽管我知道不再推荐使用@IdClass) 我的意思是,类中应该有两个属性:@Id @Column private String机构;和@Id @Column 私有字符串竞争;只是为了指定PK对吗? @Kawu 很抱歉,但老实说,在一个小评论框中讨论这个问题太难了。我什至不确定我是否理解你在说什么。如果您还有其他具体问题,我建议您选择一个 JPA 实现并进行一些试验,或者发布一个带有完整示例(和 JPA 版本)的 new 问题。这会让事情变得更容易。【参考方案2】:

我通常通过这张图区分这两者:

使用PrimaryKeyJoinColumn

使用JoinColumn

【讨论】:

@yusher,PrimaryKeyJoinColumn使用相同的主键值连接两个表,JoinColumn,主表的主键将成为另一个表的外键。【参考方案3】:

我知道这是一篇旧帖子,但如果您想要一个单向关系或多个表都共享相同的 ID,那么使用 PrimaryKeyColumn 的好时机。

一般来说这是一个坏主意,最好使用与JoinColumn 的外键关系。

话虽如此,如果您正在处理使用此类系统的旧数据库,那么这将是使用它的好时机。

【讨论】:

以上是关于JPA:@JoinColumn 和 @PrimaryKeyJoinColumn 之间的区别?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用查询而不是带有 JPA 的 @JoinColumn 映射实体关联?

JPA @JoinColumn 自定义对象类型

当我使用两个表实体时如何在 JPA @JoinColumn 中指定忽略大小写

使用 joinColumn 而不是 mappedBy 有啥危害?

jpa hibernate @OneToOne @JoinColumn referencedColumnName 被忽略

SpringData JPA多表关联操作