如何使用 Hibernate 将一个表的主键用作另一个表的主键
Posted
技术标签:
【中文标题】如何使用 Hibernate 将一个表的主键用作另一个表的主键【英文标题】:How to use the Primary Key of one table as Primary Key of another using Hibernate 【发布时间】:2022-01-22 00:59:00 【问题描述】:使用 Hibernate,我创建了两个实体 - Employee 和 EmployeeDetails。由于 EmployeeDetails 不能在 Employee 中没有相应条目的情况下存在,所以我认为我不需要 EmployeeDetails 的额外 ID,而是可以使用 Employee 实体的 ID。以下是我实现这个想法的方式:
员工实体:
@Entity
@Table(name = "employees")
@Data
public class Employee
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "employee_id")
private Long id;
@Column(name = "first_name", nullable = false)
private String firstName;
@Column(name = "last_name", nullable = false)
private String lastName;
@OneToOne(cascade = CascadeType.ALL)
EmployeeDetails employeeDetails;
员工详细信息实体:
@Entity
@Table(name = "employee_details")
@Data
public class EmployeeDetails
@Id
private Long id;
@Column(name = "address")
private String address;
@Column(name = "e_mail", nullable = false)
private String eMail;
@Column(name = "phone")
private String phone;
@MapsId
@OneToOne(mappedBy = "employeeDetails", cascade = CascadeType.ALL)
@JoinColumn(name = "employee_id")
private Employee employee;
通过将 @MapsId
注释添加到 EmployeeDetails 中的员工变量,我应该将 Employee-entity 的主键分配给 EmployeeDetails 的 Id 列。
在第二步中,我已将一些数据写入我的两个表中。
mysql 数据库中的员工表:
employee_id first_name last_name employee_details_employee_id
1 John Smith null
2 Jennifer Adams null
最后一列是由 Hibernate 生成的。我不明白为什么。它似乎是一些用于识别的列,但我不需要它。
MySQL 数据库中的employee_details 表:
employee_id address e_mail phone
1 null john.smith@gmail.com null
2 null jennifer.adams@gmail.com null
我只给员工分配了一封电子邮件。令人惊讶的是,该数据库表中没有员工条目。反正我真的不需要它,但我期待它。所以,是的,我认为我做错了什么,非常感谢一些帮助。
【问题讨论】:
【参考方案1】:改变mappedBy侧,这里有用的链接
https://vladmihalcea.com/change-one-to-one-primary-key-column-jpa-hibernate/ https://vladmihalcea.com/the-best-way-to-map-a-onetoone-relationship-with-jpa-and-hibernate/ https://javabydeveloper.com/one-one-bidirectional-association/
@Entity
@Table(name = "employees")
@Data
public class Employee
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "employee_id")
private Long id;
@Column(name = "first_name", nullable = false)
private String firstName;
@Column(name = "last_name", nullable = false)
private String lastName;
@OneToOne(mappedBy = "employee", cascade = CascadeType.ALL)
EmployeeDetails employeeDetails;
Entity
@Table(name = "employee_details")
@Data
public class EmployeeDetails
@Id
private Long id;
@Column(name = "address")
private String address;
@Column(name = "e_mail", nullable = false)
private String eMail;
@Column(name = "phone")
private String phone;
@MapsId
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "employee_id")
private Employee employee;
【讨论】:
【参考方案2】:@MapId
在使用 Hibernate 时不是一个流行的解决方案。
也许在您的情况下,@Embeddable
会是更好的选择?
如果我理解正确,EmployeeDetails
不能在没有关联的Employee
的情况下存在。所以,EmployeeDetails
可以是 Employee
中的一个字段作为可嵌入字段:
@Entity
@Table(name = "employees")
@Data
public class Employee
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "employee_id")
private Long id;
@Column(name = "first_name", nullable = false)
private String firstName;
@Column(name = "last_name", nullable = false)
private String lastName;
@Embedded
EmployeeDetails employeeDetails;
那么EmployeeDetails
不需要ID和与员工的关系:
@Embeddable
public class EmployeeDetails
@Column(name = "address")
private String address;
@Column(name = "e_mail", nullable = false)
private String eMail;
@Column(name = "phone")
private String phone;
如您所见,现在数据库中只有一张表employees
,但在我们的休眠模型中,我们有两个分开的对象。可能没有Employee
实体就不需要EmployeeDetails
,这样构造效率更高。
如果您确实需要与Employee
相关的EmployeeDetails
的分隔表,我建议创建标准的一对一映射而不是@MapId
构造。
【讨论】:
以上是关于如何使用 Hibernate 将一个表的主键用作另一个表的主键的主要内容,如果未能解决你的问题,请参考以下文章