如何使用 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 将一个表的主键用作另一个表的主键的主要内容,如果未能解决你的问题,请参考以下文章

Hibernate Envers 管理的审计表的主键是啥?

如何使用 EFCore 获取一个表的主键计数到另一个表

如何更新一个主键是另一个表的主键的表?

Hibernate的一对一关联关系

hibernate表关系

hibernate一对一关联