Java 在JPA中链接不同实体类型的最佳方法

Java 在JPA中链接不同实体类型的最佳方法,java,hibernate,jpa,inheritance,orm,Java,Hibernate,Jpa,Inheritance,Orm,短版适用于草率者: 在我的域模型中,有各种表/实体具有相同的字段(UUID)。在一个表中,我需要将这些实体的行/实例链接到其他JPA管理的实体。换句话说,该链接表中字段的实例不会预先知道。我能想到的两种方法是: 使用抽象实体和每类表策略,或 使用@MappedSuperClass将实例的类名也存储在链接表中,或者使用类似的方法来定义从正确的表中获取实际实例的逻辑 两者在复杂性和性能方面各有优缺点。你认为哪一个是最好的,是否有第三种选择,或者你过去是否尝试过类似的方法,并且会提出建议/强烈警告

短版适用于草率者:

在我的域模型中,有各种表/实体具有相同的字段(UUID)。在一个表中,我需要将这些实体的行/实例链接到其他JPA管理的实体。换句话说,该链接表中字段的实例不会预先知道。我能想到的两种方法是:

  • 使用抽象实体和每类表策略,或
  • 使用
    @MappedSuperClass
    将实例的类名也存储在链接表中,或者使用类似的方法来定义从正确的表中获取实际实例的逻辑
两者在复杂性和性能方面各有优缺点。你认为哪一个是最好的,是否有第三种选择,或者你过去是否尝试过类似的方法,并且会提出建议/强烈警告

长版本如果您需要更多背景:

我有一个数据库/对象模型,其中许多类型都有一个公共字段:通用唯一标识符(UUID)。原因是这些类型的实例可能会发生更改。这些更改遵循命令模型,并且可以封装它们的数据并将其自身持久化。让我们把这种变化称为“突变”。必须能够找出任何给定实体的数据库中存在哪些突变,反之亦然,存储的突变在哪个实体上运行

以以下带有UUID的实体为例(极其简化):

为了存储“突变”,我们使用一个名为
MutationHolder
的表/实体。要将突变与其目标实体联系起来,有一个
MutationEntityLink
。这些数据不直接出现在
MutationHolder
上的唯一原因是,可以有直接或间接的链接,但这在这里并不重要,所以我省略了它:

问题归结为如何在
MutationEntityLink
中对
实体
字段建模。我可以想到两种方法

第一个是用UUID字段创建一个抽象的
@Entity
注释类<代码>客户,
合同
地址
将对其进行扩展。因此,这是一个表每类策略。我假设我可以使用它作为
实体
字段的类型,尽管我不确定。然而,我担心这可能会严重影响性能,因为JPA需要查询许多表才能找到实际的实例

第二种方法是简单地使用
@MappedSuperClass
并将实体的UUID存储在
MutationEntityLink
entity
字段中。为了获得具有该UUID的实际实体,我必须以编程方式解决它。添加一个具有实体类名的附加列,或者其他允许我识别它或将它粘贴到JPQL查询中的内容,就可以了。这需要更多的工作,但似乎更有效率。如果需要,我并不反对编写一些实用程序类或进行一些反射/自定义注释工作

我的问题是这些方法中哪一种看起来最好?或者,你可能会有更好的建议,或者注意到我遗漏了什么;例如,也许有一种方法可以添加一个类型列,即使使用表\每\类继承也可以将JPA指向正确的表?也许你尝试过这样的事情,想提醒我一些可能出现的问题

其他一些信息:

  • 我们创建数据库模式,以便可以添加任何需要的内容
  • 单表继承策略不是一个选项。表必须保持不同。出于同样的原因,联合继承似乎也不太合适
  • JPA提供者是Hibernate,使用不属于JPA标准的东西不是问题

如果实体除了uuid之外没有任何共同点,我将使用您描述的第二种方法:使用
MappedSuperclass
。使公共超类成为实体将阻止您在需要时使用不同的继承策略,将需要为该超级实体创建一个表,即使不存在实例,从业务角度来看,这是错误的


链接本身可以以多种方式实现,例如,您可以为每个要映射的实体创建子类
MutationEntityLink
(例如
CustomerMutationEntityLink
等),或者按照您的描述执行,即仅存储uuid以及一些鉴别器/类型信息,并通过编程进行解析(顺便说一句,我们正在使用类似的方法。).

在继承关联/方法/属性时,您需要使用
@MappedSuperclass
,而当您有实体和子实体时,通常使用TABLE_PER_类。如果模型中有实体与基类关联,则使用TABLE_PER_类,因为基类的行为类似于实体。否则,since基类将包括属性/属性和方法,这些属性/属性和方法对于彼此不相关的实体来说是通用的,使用
@MappedSuperclass
将是一个更好的主意

示例1:您需要为一些不同的活动设置警报,如“吃药”、“打电话给妈妈”、“去看医生”等。警报消息的内容无关紧要,您需要一个提醒。因此,请使用TABLE_PER_类,因为alarm message是您的基类,在这里类似于一个实体


示例2:假设基类AbstractDomainObject允许您为每个对象创建登录ID、登录名、创建/修改日期,如果没有实体与基类有关联,则需要指定关联以便稍后清除,如“公司”、“大学”等等。在这种情况下,使用
@MappedSuperclass
会更好。

很高兴听到您实际使用了这种方法。这表明它是可行的。我认为子类化Mutati