Как смоделировать отношения один-к-одному в JPA, когда "родительская" таблица имеет составной PK?
В то время как существует много информации о том, как моделировать, в JPA (2), взаимно однозначное отношение или сущность , имеющая естественный ключ, я не смог найти ясного / простого ответа на то, как моделировать ситуацию, когда у нас есть и то, и другое, т. е. отношения один-к-одному, в которых родительская таблица имеет естественный ключ. Вполне возможно, что я пропустил такой учебник; если это так, то указание мне на один из них также может быть ответ.
И, как много раз с JPA и noobs, такими как я, в тот момент, когда вам нужно немного больше, чем самая базовая модель, вы можете быстро ударить в стену.
Следовательно, рассматривая следующую модель БД:
Какова будет соответствующая JPA-аннотированная объектная модель? (Я избавляю вас, ребята, от того, что я пытался сделать, так как не хочу влиять на ответ...)
Рекомендации по производительности также приветствуются (например, "один ко многим может выполняйте быстрее" и т. д.)!
Спасибо,
1 ответ:
Отображение составного ключа не является сложным, как показано в следующей статье .
Составной идентификатор построен из двух числовых столбцов, поэтому отображение выглядит следующим образом:
@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()); } }
Родительский класс, выглядит следующим образом:
@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; } }
А ребенок такой:
@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 .