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

Time:12-21

Using Hibernate, I have created two entities - Employee and EmployeeDetails. Since EmployeeDetails cannot exist without a corresponding entry in Employee, I figured I don't need an extra ID for EmployeeDetails, but could instead use the ID of the Employee entity. Here is how I have implemented this idea:

Employee-Entity:

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

Employee-Details-Entity:

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

By adding the @MapsId annotation to the employee-variable inside EmployeeDetails, I should be assigning the primary key of the Employee-entity to the Id-column of EmployeeDetails.

In a second step, I have written some data into both of my tables.

employee table in MySQL database:

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

The last column was somehow generated by Hibernate. I don't understand why. It appears to be some column for identification, but I don't need it.

employee_details table in MySQL database:

employee_id    address    e_mail                     phone
1              null       [email protected]       null
2              null       [email protected]   null

I have only assigned an e-mail to the employees. Surprisingly, there is no employee-entry in this database table. I don't really need it anyways, but I was expecting it. So yeah, I think I am doing something terribly wrong and would really appreciate some help.

CodePudding user response:

@MapId is not a popular solution in work with Hibernate. Maybe in your case, @Embeddable will be a better option?

If I understand correctly, EmployeeDetails cannot exist without correlated Employee. So, EmployeeDetails could be a field in Employee as an embeddable field:

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

Then EmployeeDetails doesn't need ID and relation with the employee:

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

As you can see, now in the database it's only one table employees, but in our hibernate model, we have two separated objects. Probably you don't need EmployeeDetails without Employee entity, so there is more efficient construction.

If you really need a separated table for EmployeeDetails with relation to Employee I recommend creating standard one-to-one mapping instead of @MapId construction.

CodePudding user response:

Change mappedBy side, here useful links

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