Tình hình
Tôi có một Entity với một DiscriminatorColumn
, cấu hình cho thừa kế bảng duy nhất:DiscriminatorColumn như một phần của khóa chính/id
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="TYPE")
public class ContainerAssignment{
...
}
'ContainerAssignment' có một tham chiếu đến một Entity:
@JoinColumn(name="CONTAINER_ID")
private Container container;
Vùng chứa có thể có một ContainerAssignment
của mỗi TYPE. Điều này có nghĩa là khóa chính của bảng ContainerAssignment
được xác định bởi CONTAINER_ID
và TYPE
.
ContainerAssignment
có một số lớp con, ví dụ:
@Entity
@DiscriminatorValue("SOME_TYPE")
public class SomeTypeOfContainerAssignment extends ContainerAssignment{
...
}
Sẽ chỉ có một ví dụ SomeTypeOfContainerAssignment
cho CONTAINER_ID
nhất định.
Vấn đề
Nếu tôi xác định JPA @Id
như chỉ là container trên bàn ContainerAssignment, tôi có thể làm entityManager.find(SomeTypeOfContainerAssignment.class, containerId)
, đó là rất tốt. Điều này chạy một cái gì đó dọc theo dòng SELECT * FROM CONTAINER_ASSIGNMENT WHERE CONTAINER_ID = 1 AND TYPE = 'SOME_TYPE';
. Nó biết nó cần kiểm tra TYPE ở đây, vì chú thích @DiscriminatorValue("SOME_TYPE")
trên thực thể.
Tuy nhiên, điều này có nghĩa là các tham chiếu ngược từ vùng chứa đến vùng chứaAssignment bị hỏng vì Vùng chứa không thực sự là khóa chính. Ví dụ: nếu Vùng chứa có một số @OneToOne(mappedBy=container) private SomeTypeOfContainerAssignment assignment;
, khi bạn đọc trong một vùng chứa, nó sẽ đọc trong phần gán bởi một cái gì đó như SELECT * FROM CONTAINER_ASSIGNMENT WHERE CONTAINER_ID = 1;
mà không cần kiểm tra loại. Điều này mang lại cho nó tất cả các nhiệm vụ cho một container, và sau đó nó chọn một trong những dường như ngẫu nhiên, có khả năng loại sai, trong trường hợp đó, nó ném một ngoại lệ.
Nếu thay vào đó, tôi xác định JPA @Id
của ContainerAssignment làm id tổng hợp bằng cách sử dụng vùng chứa và loại, tham chiếu đến các lớp con của công việc của ContainerAssignment.
Tuy nhiên, tôi không thể làm entityManager.find(SomeTypeOfContainerAssignment.class, containerId)
, vì containerId không phải là id. Tôi phải làm entityManager.find(SomeTypeOfContainerAssignment.class, new MyPk(containerId, "SOME_TYPE"))
, dường như đánh bại điểm @DiscriminatorValue("SOME_TYPE")
. Tôi cũng có thể chỉ sử dụng một thực thể ContainerAssignment duy nhất nếu tôi phải chỉ định kiểu trên tìm anyway.
Câu hỏi
Có cách nào để có tài liệu tham khảo làm việc để phụ lớp học của một Entity bảng thừa kế duy nhất mà khóa chính trên bảng là tổng hợp trên cột phân biệt, trong khi cũng có khả năng EntityManager.find
bởi chỉ (các) phần của khóa chính không phải là người phân biệt đối xử?
Cảm ơn câu trả lời của bạn, nhưng nó không thực sự giải quyết được câu hỏi - có cách nào để đặt loại 'DiscriminatorColumn' bên trong PK không? Tôi đồng ý rằng một PK nhân tạo là lựa chọn tốt nhất, nhưng trong nhiều hệ thống, chúng tôi không thể kiểm soát lược đồ và phải đối phó với các PK tổng hợp. –
Cũng lưu ý rằng KHÔNG BAO GIỜ sử dụng các phím tổng hợp chính là một mẫu chống, theo sách Bill Karwin. – atorres