Ситуация
У меня есть сущность с DiscriminatorColumn
, настроенная для наследования одной таблицы:
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="TYPE")
public class ContainerAssignment{
...
}
«ContainerAssignment» имеет ссылку на другой объект:
@JoinColumn(name="CONTAINER_ID")
private Container container;
Контейнер может иметь по одному ContainerAssignment
каждого ТИПА. Это означает, что первичный ключ таблицы ContainerAssignment
определяется CONTAINER_ID
и TYPE
.
ContainerAssignment
имеет несколько подклассов, например.
@Entity
@DiscriminatorValue("SOME_TYPE")
public class SomeTypeOfContainerAssignment extends ContainerAssignment{
...
}
Для данного CONTAINER_ID
будет только один экземпляр SomeTypeOfContainerAssignment
.
Проблема
Если я определяю JPA @Id
просто как Container в таблице ContainerAssignment, я могу сделать entityManager.find(SomeTypeOfContainerAssignment.class, containerId)
, и это здорово. Это работает что-то вроде SELECT * FROM CONTAINER_ASSIGNMENT WHERE CONTAINER_ID = 1 AND TYPE = 'SOME_TYPE';
. Он знает, что здесь нужна проверка TYPE из-за аннотации @DiscriminatorValue("SOME_TYPE")
на Entity.
Однако это означает, что обратные ссылки из Container в ContainerAssignment прерываются, поскольку Container на самом деле не является первичным ключом. Например, если у контейнера есть @OneToOne(mappedBy=container) private SomeTypeOfContainerAssignment assignment;
, когда вы читаете в контейнере, он будет читать в присваивании что-то вроде SELECT * FROM CONTAINER_ASSIGNMENT WHERE CONTAINER_ID = 1;
без проверки типа. Это дает ему все назначения для контейнера, а затем он выбирает одно, казалось бы, случайное, потенциально неправильного типа, и в этом случае генерирует исключение.
Если вместо этого я определяю JPA @Id
ContainerAssignment как составной идентификатор, используя контейнер и тип, ссылки на подклассы ContainerAssignment работают нормально.
Однако я не могу сделать entityManager.find(SomeTypeOfContainerAssignment.class, containerId)
, потому что containerId не является идентификатором. Я должен сделать entityManager.find(SomeTypeOfContainerAssignment.class, new MyPk(containerId, "SOME_TYPE"))
, что, кажется, противоречит пункту @DiscriminatorValue("SOME_TYPE")
. С тем же успехом я мог бы просто использовать одну сущность ContainerAssignment, если мне все равно нужно указать тип при поиске.
Вопрос
Есть ли способ иметь рабочие ссылки на подклассы объекта наследования одной таблицы, где первичный ключ в таблице является составным в столбце дискриминатора, а также иметь возможность EntityManager.find
только частью (частями) первичного ключа, который не дискриминатор?