如何使用一个 table 的主键作为另一个使用 Hibernate 的主键

How to use the Primary Key of one table as Primary Key of another using Hibernate

我使用 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;
}

通过向 EmployeeDetails 中的员工变量添加 @MapsId 注释,我应该将 Employee 实体的主键分配给 EmployeeDetails 的 Id 列。

第二步,我将一些数据写入了我的两个 tables。

MySQL 数据库中的员工 table:

employee_id    first_name    last_name    employee_details_employee_id
1              John          Smith        null
2              Jennifer      Adams        null

最后一列是由 Hibernate 以某种方式生成的。我不明白为什么。好像是什么识别栏,我不需要

employee_details table 在 MySQL 数据库中:

employee_id    address    e_mail                     phone
1              null       john.smith@gmail.com       null
2              null       jennifer.adams@gmail.com   null

我只给员工分配了一封电子邮件。令人惊讶的是,此数据库中没有员工条目 table。反正我真的不需要它,但我期待它。所以,是的,我认为我做错了一些事情,非常感谢您的帮助。

@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;
}

如您所见,现在在数据库中它只有一个 table employees,但在我们的休眠模型中,我们有两个分离的对象。可能你不需要 EmployeeDetails 没有 Employee 实体,所以有更有效的构造。

如果您真的需要 EmployeeDetailsEmployee 的分离 table,我建议创建标准的一对一映射而不是 @MapId 构造。

改变mappedBy side,这里是有用的链接

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;
}