Spy*_*cho 10 orm jpa composite-primary-key discriminator
我有一个实体,有一个DiscriminatorColumn,配置为单表继承:
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="TYPE")
public class ContainerAssignment{
...
}
Run Code Online (Sandbox Code Playgroud)
'ContainerAssignment'引用了另一个实体:
@JoinColumn(name="CONTAINER_ID")
private Container container;
Run Code Online (Sandbox Code Playgroud)
容器可以具有ContainerAssignment每种类型中的一种.这意味着ContainerAssignment表的主键由CONTAINER_ID和定义TYPE.
ContainerAssignment 有一些子类,例如
@Entity
@DiscriminatorValue("SOME_TYPE")
public class SomeTypeOfContainerAssignment extends ContainerAssignment{
...
}
Run Code Online (Sandbox Code Playgroud)
SomeTypeOfContainerAssignment给定的只有一个实例CONTAINER_ID.
如果我将JPA定义@Id为ContainerAssignment表上的Container,我可以做到entityManager.find(SomeTypeOfContainerAssignment.class, containerId),这很好.这有点像SELECT * FROM CONTAINER_ASSIGNMENT WHERE CONTAINER_ID = 1 AND TYPE = 'SOME_TYPE';.它知道它需要在这里进行TYPE检查,因为@DiscriminatorValue("SOME_TYPE")实体上有注释.
但是,这意味着从Container到ContainerAssignment的后引用中断,因为Container实际上不是主键.例如,如果Container有一个@OneToOne(mappedBy=container) private SomeTypeOfContainerAssignment assignment;,当你读入一个容器时,它将通过类似的方式读取赋值SELECT * FROM CONTAINER_ASSIGNMENT WHERE CONTAINER_ID = 1;,而不进行类型检查.这给了它一个容器的所有赋值,然后它看起来随机选择一个,可能是错误的类型,在这种情况下,它抛出一个异常.
相反,我@Id使用容器和类型将ContainerAssignment 的JPA定义为复合id,对ContainerAssignment的子类的引用工作正常.
但是,我不能这样做entityManager.find(SomeTypeOfContainerAssignment.class, containerId),因为containerId不是id.我必须这样做entityManager.find(SomeTypeOfContainerAssignment.class, new MyPk(containerId, "SOME_TYPE")),这似乎打败了这一点@DiscriminatorValue("SOME_TYPE").如果我必须在find上指定类型,我可能只使用一个ContainerAssignment实体.
有没有办法对单个表继承实体的子类进行工作引用,其中表上的主键在鉴别器列上是复合的,同时也只能EntityManager.find由主键的部分组成.不是鉴别者?
如果Container有一个双向 OneToOne SomeTypeOfContainerAssignment,它扩展了ContainerAssignment,那么容器字段不应该在 中定义和映射ContainerAssignment,而应该在 中SomeTypeOfContainerAssignment:
public class Container {
@Id
private Long id;
@OneToOne(mappedBy = "container")
private SomeTypeOfContainerAssignment someTypeOfContainerAssignment;
}
public class ContainerAssignment {
@Id
private Long id;
}
public class SomeTypeOfContainerAssignment extends ContainerAssignment {
@OneToOne
private Container container;
}
Run Code Online (Sandbox Code Playgroud)
如果所有类型的容器分配都与 COntainer 存在 OneToOne 关联,则可以将 Container 定义为
public abstract class ContainerAssignment {
@Id
private Long id;
public abstract Container getContainer();
public abstract void setContainer(Container container);
}
Run Code Online (Sandbox Code Playgroud)
老实说,我不知道是否允许您使用表中相同的联接列来映射@OneToOne container每个子类的字段。
我认为这是你能拥有的最好的。如果将容器字段放在基类中,则必须将关联定义为 OneToMany/ManyToOne 关联,因为它才是真正的关联。
我不认为你想做的事情是可能的,而且我不会搞乱复合PK,因为他们有充分的理由被劝阻,而且使用起来是一场噩梦。