当 "parent" table 具有复合 PK 时,如何在 JPA 中建模一对一关系?
How to model a one-to-one relationship in JPA when the "parent" table has a composite PK?
虽然有很多关于如何建模的信息,但在 JPA (2) 中,一对一关系 OR 一个 具有自然键的实体 ,对于如何对我们所拥有的情况进行建模,我一直无法找到一个清晰/简单的答案两者,即 一对一关系,其中父 table 具有自然键 。很明显,我可能错过了这样的教程;如果是这样,请指点我一个也可能是答案。
而且,像我这样的 JPA 和新手很多次,当需要比最基本的模型多一点的时候,很快就会碰壁。
因此,考虑以下数据库模型:
相应的 JPA 注释对象模型是什么? (因为我不想影响答案,所以我不会让你们知道我尝试过的事情...)
也欢迎提供性能建议(例如 "a one-to-many could perform faster" 等)!
谢谢,
复合标识符由两个数字列构成,因此映射如下所示:
@Embeddable
public class EmployeeId implements Serializable {
private Long companyId;
private Long employeeId;
public EmployeeId() {
}
public EmployeeId(Long companyId, Long employeeId) {
this.companyId = companyId;
this.employeeId = employeeId;
}
public Long getCompanyId() {
return companyId;
}
public Long getEmployeeId() {
return employeeId;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof EmployeeId)) return false;
EmployeeId that = (EmployeeId) o;
return Objects.equals(getCompanyId(), that.getCompanyId()) &&
Objects.equals(getEmployeeId(), that.getEmployeeId());
}
@Override
public int hashCode() {
return Objects.hash(getCompanyId(), getEmployeeId());
}
}
parentclass,看起来如下:
@Entity(name = "Employee")
public static class Employee {
@EmbeddedId
private EmployeeId id;
private String name;
@OneToOne(mappedBy = "employee")
private EmployeeDetails details;
public EmployeeId getId() {
return id;
}
public void setId(EmployeeId id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public EmployeeDetails getDetails() {
return details;
}
public void setDetails(EmployeeDetails details) {
this.details = details;
}
}
而 child 是这样的:
@Entity(name = "EmployeeDetails")
public static class EmployeeDetails {
@EmbeddedId
private EmployeeId id;
@MapsId
@OneToOne
private Employee employee;
private String details;
public EmployeeId getId() {
return id;
}
public void setId(EmployeeId id) {
this.id = id;
}
public Employee getEmployee() {
return employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
this.id = employee.getId();
}
public String getDetails() {
return details;
}
public void setDetails(String details) {
this.details = details;
}
}
一切正常:
doInJPA(entityManager -> {
Employee employee = new Employee();
employee.setId(new EmployeeId(1L, 100L));
employee.setName("Vlad Mihalcea");
entityManager.persist(employee);
});
doInJPA(entityManager -> {
Employee employee = entityManager.find(Employee.class, new EmployeeId(1L, 100L));
EmployeeDetails employeeDetails = new EmployeeDetails();
employeeDetails.setEmployee(employee);
employeeDetails.setDetails("High-Performance Java Persistence");
entityManager.persist(employeeDetails);
});
doInJPA(entityManager -> {
EmployeeDetails employeeDetails = entityManager.find(EmployeeDetails.class, new EmployeeId(1L, 100L));
assertNotNull(employeeDetails);
});
doInJPA(entityManager -> {
Phone phone = entityManager.find(Phone.class, "012-345-6789");
assertNotNull(phone);
assertEquals(new EmployeeId(1L, 100L), phone.getEmployee().getId());
});
代码可用 GitHub。
虽然有很多关于如何建模的信息,但在 JPA (2) 中,一对一关系 OR 一个 具有自然键的实体 ,对于如何对我们所拥有的情况进行建模,我一直无法找到一个清晰/简单的答案两者,即 一对一关系,其中父 table 具有自然键 。很明显,我可能错过了这样的教程;如果是这样,请指点我一个也可能是答案。
而且,像我这样的 JPA 和新手很多次,当需要比最基本的模型多一点的时候,很快就会碰壁。
因此,考虑以下数据库模型:
相应的 JPA 注释对象模型是什么? (因为我不想影响答案,所以我不会让你们知道我尝试过的事情...)
也欢迎提供性能建议(例如 "a one-to-many could perform faster" 等)!
谢谢,
复合标识符由两个数字列构成,因此映射如下所示:
@Embeddable
public class EmployeeId implements Serializable {
private Long companyId;
private Long employeeId;
public EmployeeId() {
}
public EmployeeId(Long companyId, Long employeeId) {
this.companyId = companyId;
this.employeeId = employeeId;
}
public Long getCompanyId() {
return companyId;
}
public Long getEmployeeId() {
return employeeId;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof EmployeeId)) return false;
EmployeeId that = (EmployeeId) o;
return Objects.equals(getCompanyId(), that.getCompanyId()) &&
Objects.equals(getEmployeeId(), that.getEmployeeId());
}
@Override
public int hashCode() {
return Objects.hash(getCompanyId(), getEmployeeId());
}
}
parentclass,看起来如下:
@Entity(name = "Employee")
public static class Employee {
@EmbeddedId
private EmployeeId id;
private String name;
@OneToOne(mappedBy = "employee")
private EmployeeDetails details;
public EmployeeId getId() {
return id;
}
public void setId(EmployeeId id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public EmployeeDetails getDetails() {
return details;
}
public void setDetails(EmployeeDetails details) {
this.details = details;
}
}
而 child 是这样的:
@Entity(name = "EmployeeDetails")
public static class EmployeeDetails {
@EmbeddedId
private EmployeeId id;
@MapsId
@OneToOne
private Employee employee;
private String details;
public EmployeeId getId() {
return id;
}
public void setId(EmployeeId id) {
this.id = id;
}
public Employee getEmployee() {
return employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
this.id = employee.getId();
}
public String getDetails() {
return details;
}
public void setDetails(String details) {
this.details = details;
}
}
一切正常:
doInJPA(entityManager -> {
Employee employee = new Employee();
employee.setId(new EmployeeId(1L, 100L));
employee.setName("Vlad Mihalcea");
entityManager.persist(employee);
});
doInJPA(entityManager -> {
Employee employee = entityManager.find(Employee.class, new EmployeeId(1L, 100L));
EmployeeDetails employeeDetails = new EmployeeDetails();
employeeDetails.setEmployee(employee);
employeeDetails.setDetails("High-Performance Java Persistence");
entityManager.persist(employeeDetails);
});
doInJPA(entityManager -> {
EmployeeDetails employeeDetails = entityManager.find(EmployeeDetails.class, new EmployeeId(1L, 100L));
assertNotNull(employeeDetails);
});
doInJPA(entityManager -> {
Phone phone = entityManager.find(Phone.class, "012-345-6789");
assertNotNull(phone);
assertEquals(new EmployeeId(1L, 100L), phone.getEmployee().getId());
});
代码可用 GitHub。