什么是 @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 Key 到 Patient 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 我有两个实体 Publisher 和 Book 并且它们都有双向关联,但 @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?