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