什么是 @JoinColumn 以及它在 Hibernate 中的使用方式

Posted

技术标签:

【中文标题】什么是 @JoinColumn 以及它在 Hibernate 中的使用方式【英文标题】:what is @JoinColumn and how it is used in Hibernate 【发布时间】:2016-09-29 06:14:29 【问题描述】:

我已经阅读了很多关于 @JoinColumn 的内容,但我仍然不明白它背后的想法。

病床

CREATE TABLE patient (
patient_id BIGINT NOT NULL,
first_name VARCHAR(255) NOT NULL,
last_name VARCHAR(255) NOT NULL,
PRIMARY KEY(patient_id));

车辆表

CREATE TABLE vehicles (
patient_id BIGINT NOT NULL,
vehicle_id BIGINT NOT NULL,
vehicle_manufacturer VARCHAR(255),
PRIMARY KEY (vehicle_id),
CONSTRAINT patienthasmanyvehicle FOREIGN KEY(patient_id) REFERENCES patient(patient_id));

病人分类

@OneToMany(mappedBy = "patient")
    private Collection<Vehicle> patientVehicles = new ArrayList<Vehicle>();

车辆类别

@ManyToOne
@JoinColumn(name="patient_id")
private Patient patient;

我很困惑Vehicle类部分是什么,它们之间的关系是什么

Vehicle Class ---- Entity
@JoinColumn(name="patient_id") ---- annotation
private Patient patient ----field

它说; Vehicle Entity 有一个 Foreign KeyPatient entity,名为 patient_id。 将 patient_id 添加为 Vehicle Entity 表

中的列

JoinColumn 的 name 参数是否应该始终是外键或主键?

我一直在阅读这篇文章,但我仍然感到困惑。 JPA JoinColumn vs mappedBy

【问题讨论】:

【参考方案1】:

车辆类----实体 @JoinColumn(name="patient_id")----注解 私人患者患者----现场

以上代码将在 Vehicle 类中生成一个列 patient_id(外键),该列将指向 Patient Class 主键。

MappedBy - 这个属性告诉我们这个关系将由 Vehicle 类管理。例子。如果我们插入一个车辆,那么如果 cascadetype 是 all/save,就会注入两个 SQL。第一个 SQL 将在 Patient 表中注入详细信息,第二个 SQL 将在 Vehicle 表中注入车辆详细信息,其中 Vehicle 列的 Patient_id 列指向插入的 Patient 元组。

【讨论】:

但是为什么当我运行我的 Vehicle Table 中的 patient_id(生成的列是 FK) 没有任何价值代码? @zenlloyd 对于单向关联这是不可能的。对于双向来说是正常的。 有没有办法验证外键(Vehicle 表中的patient_id)是否真的映射到了 patients 表中? @zenlloyd。要正确映射患者对象,您需要确保在车辆对象中设置了患者属性。如果没有设置这个值,那么 Patient_id 将被注入 null 值。【参考方案2】:

连接列所在的表取决于上下文。

如果联接是针对使用外键映射策略的 OneToOne 或 ManyToOne 映射,则外键列在源实体的表中或可嵌入的。

如果连接是针对使用外键映射策略的单向 OneToMany 映射,则外键在目标实体的表中。

如果连接是针对多对多映射或单对一或使用连接表的双向多对一/单对多映射,则外键位于连接表中。

如果联接是针对元素集合,则外键在集合表中。

【讨论】:

【参考方案3】:

为什么patient_id(生成的列是 FK)在 当我运行我的代码时,Vehicle Table 没有任何价值?

@JoinColumn 所做的只是指定用于加入实体关联或元素集合的列。由于您已将 @JoinColumn 与 Patient 类对象关联,这就是在 Patient 表上创建外键的原因。

更多信息请参考https://docs.jboss.org/hibernate/jpa/2.1/api/javax/persistence/JoinColumn.html

【讨论】:

此语句:“由于您已将 @JoinColumn 与 Patient 类对象关联,这就是在 Patient 表上创建外键的原因。”是不正确的。这就是原因:“如果联接是针对使用外键映射策略的 OneToOne 或 ManyToOne 映射,则外键列在源实体的表中或可嵌入的。”【参考方案4】:

通过连接表的单向关联

@Entity
class Patient 

    @OneToMany
    private Collection<Vehicle> vehicles = new ArrayList<Vehicle>();



@Entity
class Vehicle 


通过连接表的双向关联

@Entity
class Patient 

    @OneToMany
    private Collection<Vehicle> vehicles = new ArrayList<Vehicle>();



@Entity
class Vehicle 

    @ManyToOne(fetch = FetchType.LAZY)
    private Patient patient;


通过外键的单向关联

@Entity
class Patient 

    @OneToMany
    @JoinColumn
    private Collection<Vehicle> vehicles = new ArrayList<Vehicle>();



@Entity
class Vehicle 


通过外键的双向关联

@Entity
class Patient 

    @OneToMany(mappedBy = "patient")
    private Collection<Vehicle> vehicles = new ArrayList<Vehicle>();



@Entity
class Vehicle 

    @ManyToOne(fetch = FetchType.LAZY)
    private Patient patient;


通过外键与外列名称规范的双向关联

@Entity
class Patient 

    @OneToMany(mappedBy = "patient")
    private Collection<Vehicle> vehicles = new ArrayList<Vehicle>();



@Entity
class Vehicle 

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name="patient_id")
    private Patient patient;


这是使用@JoinColumn的基本出发点。

要验证外键(Vehicle 表中的patient_id)是否真的映射到患者表中,您可以使用@JoinColumn(nullable = false)

@Entity
class Vehicle 

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name="patient_id", nullable = false)
    private Patient patient


【讨论】:

当您指定@OneToMany 时,不是有隐含的@JoinColum 吗?我的意思是通过连接表进行关联,通过外键进行单向关联,而不仅仅是默认的库名和手动库名? @sql_dummy @JoinColumn 不用于连接表。我不明白第二个问题。对于单向和双向关联,您将拥有相同的数据库架构。 我的意思是当我指定@OneToMany 时没有隐式指定@JoinColumn?我有这个疑问是因为通过Debug 文件我看到该字段有类似的binding 天气我明确使用@JoinColumn 或不。 (我想我的问题的答案很可能是“否”,但为什么是相似的binding 你能回答here @v.ladynev 我有两个实体 PublisherBook 并且它们都有双向关联,但 @JoinColumn 在 @987654342 上指定@ 边。请问这是什么类型的关系可以回答链接:github.com/springframeworkguru/spring5webapp/tree/…【参考方案5】:

连接列是用@JoinColumn 注释声明的,它看起来像@Column 注释。它还有一个名为referencedColumnName 的参数。此参数声明目标实体中将用于连接的列。

在双向关系中,一方(并且只有一方)必须是所有者:所有者负责关联列的更新。要声明一方对关系不负责,使用属性 mappedBy。 mappedBy 指的是所有者侧关联的属性名称。

这里是示例代码:

EntityOne : 
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "TEST_ID")
    private EntityTwo entityTwo;

EntityTwo : 
      // bi-directional many-to-one association to EntityOne Here TEST_ID is the Primary key
    @OneToMany(mappedBy = "entityTwo")
    private List<EntityOne> entityOne;

【讨论】:

如何替换hbm映射文件中的@JoinColumn(name = "TEST_ID")??

以上是关于什么是 @JoinColumn 以及它在 Hibernate 中的使用方式的主要内容,如果未能解决你的问题,请参考以下文章

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

我啥时候应该在 JPA 中使用 @JoinColumn 或 @JoinTable?

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

JoinColumn解释

@JoinColumn解释

什么是元数据?以及它在android中的用途是什么