Как смоделировать отношения один-к-одному в JPA, когда "родительская" таблица имеет составной PK?


В то время как существует много информации о том, как моделировать, в JPA (2), взаимно однозначное отношение или сущность , имеющая естественный ключ, я не смог найти ясного / простого ответа на то, как моделировать ситуацию, когда у нас есть и то, и другое, т. е. отношения один-к-одному, в которых родительская таблица имеет естественный ключ. Вполне возможно, что я пропустил такой учебник; если это так, то указание мне на один из них также может быть ответ.

И, как много раз с JPA и noobs, такими как я, в тот момент, когда вам нужно немного больше, чем самая базовая модель, вы можете быстро ударить в стену.

Следовательно, рассматривая следующую модель БД:

Введите описание изображения здесь

Какова будет соответствующая JPA-аннотированная объектная модель? (Я избавляю вас, ребята, от того, что я пытался сделать, так как не хочу влиять на ответ...)

Рекомендации по производительности также приветствуются (например, "один ко многим может выполняйте быстрее" и т. д.)!

Спасибо,

1 2

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 .