gpt4 book ai didi

jpa - DiscriminatorColumn 作为主键/id 的一部分

转载 作者:行者123 更新时间:2023-12-03 14:44:53 25 4
gpt4 key购买 nike

情况
我有一个带有 DiscriminatorColumn 的实体,配置为单表继承:

@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="TYPE")
public class ContainerAssignment{
...
}
'ContainerAssignment' 引用了另一个实体:
@JoinColumn(name="CONTAINER_ID")
private Container container;
一个容器可能有一个 ContainerAssignment每个 TYPE。这意味着 ContainerAssignment 的主键表由 CONTAINER_ID 定义和 TYPE . ContainerAssignment有一些子类,例如
@Entity
@DiscriminatorValue("SOME_TYPE")
public class SomeTypeOfContainerAssignment extends ContainerAssignment{
...
}
只有一个 SomeTypeOfContainerAssignment给定 CONTAINER_ID 的实例.
问题
如果我定义 JPA @Id作为 ContainerAssignment 表上的 Container,我可以做 entityManager.find(SomeTypeOfContainerAssignment.class, containerId) ,这很棒。这与 SELECT * FROM CONTAINER_ASSIGNMENT WHERE CONTAINER_ID = 1 AND TYPE = 'SOME_TYPE'; 类似.由于 @DiscriminatorValue("SOME_TYPE"),它知道它需要在这里进行类型检查。实体上的注释。
但是,这意味着从 Container 到 ContainerAssignment 的反向引用会中断,因为 Container 并不是真正的主键。例如,如果 Container 有一个 @OneToOne(mappedBy=container) private SomeTypeOfContainerAssignment assignment; ,当你读入一个容器时,它会通过类似 SELECT * FROM CONTAINER_ASSIGNMENT WHERE CONTAINER_ID = 1; 的方式读入赋值。 , 没有类型检查。这为它提供了一个容器的所有分配,然后它似乎随机选择了一个,可能是错误的类型,在这种情况下,它会抛出异常。
如果相反,我定义了 JPA @Id ContainerAssignment 作为使用容器和类型的复合 id,对 ContainerAssignment 的子类的引用工作正常。
但是,我做不到 entityManager.find(SomeTypeOfContainerAssignment.class, containerId) ,因为 containerId 不是 id。我要做 entityManager.find(SomeTypeOfContainerAssignment.class, new MyPk(containerId, "SOME_TYPE")) ,这似乎打败了 @DiscriminatorValue("SOME_TYPE") 的观点.如果无论如何我必须在查找时指定类型,我也可能只使用单个 ContainerAssignment 实体。

有没有办法对单个表继承实体的子类进行工作引用,其中表上的主键复合在鉴别器列上,同时还能够 EntityManager.find仅通过主键的不是鉴别器的部分?

最佳答案

我将假设 ContainerAssignment 的复合主键工作正常(我真的认为它可能依赖于 JPA 实现!),并且仍然困扰您的是对 entityManager.find 和 PK 实例化的烦人调用。

我的解决方案是定义独立于 JPA API 的 finder 方法。不要将自己锁定在 JPA 上。
最简单的方法是在您的域类中定义一个静态查找器(或者,如果您想保持域解耦,请使用查找器定义另一个类,请执行 JPA。在 IoC 上挖掘以了解如何做到这一点)。

在 ContainerAssignment(或您的 finder 类):

public static <T extends ContainerAssignment> T findByPK(EntityManager manager,Class<T> type,long id) {
DiscriminatorValue val = type.getAnnotation(DiscriminatorValue.class); // this is not optimal...can be cached...
return (T) manager.find(type, new MyPk(containerId, val.getValue()));
}

在您的代码中:
SomeTypeOfContainerAssignment ca = ContainerAssignment.findByPK(entityManager,SomeTypeOfContainerAssignment.class,containerId);

请注意,将类型作为 PK 的一部分意味着您可以拥有两个具有相同 id 的不同类型的 ContainerAssignment 实例。如果您不知道它的类型,您将需要一个查询来检索 ContainerAssignment。但是,如果您的 id 是从序列生成的,您只需编写另一个 finder 方法来隐藏对 Entity Framework 的内部调用,返回结果集的第一个结果。

关于jpa - DiscriminatorColumn 作为主键/id 的一部分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11049673/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com