简短版本 用于仓促:
我的域模型中有多个表/实体具有相同的字段(UUID)。有一个表,我需要将此类实体的行/实例链接到其他 JPA 管理的实体。换句话说,该链接表中字段的实例不会预先知道。我能想到的两种方法是:
- 使用抽象实体和 TABLE_PER_CLASS 策略,或者
- 使用
@MappedSuperClass
也将实例的类名存储在链接表中,或类似的东西让我定义从正确的表中获取实际实例的逻辑。
两者在复杂性和性能方面各有优缺点。您认为哪个最好,是否有第三种选择,或者您过去是否尝试过类似的方法并且建议/强烈警告不要这样做?
长版如果你想要更多背景:
我有一个数据库/对象模型,其中许多类型都有一个公共(public)字段:通用唯一标识符 (UUID)。这样做的原因是这些类型的实例可能会发生变化。更改遵循命令模型,并且可以封装它们的数据并自身持久化。让我们称这种变化为“突变”。对于任何给定的实体,必须能够找出数据库中存在哪些突变,反之亦然,存储的突变对哪个实体进行操作。
为了存储“突变”,我们使用了一个名为 MutationHolder
的表/实体。要将突变链接到其目标实体,可以使用 MutationEntityLink
。此数据不直接位于 MutationHolder
上的唯一原因是因为可能存在直接或间接链接,但这在这里并不重要,因此我将其省略:
问题归结为如何为 MutationEntityLink
中的 entity
字段建模。我可以想到两种方法。
第一个是用UUID字段制作一个抽象的@Entity
注解类。 Customer
、Contract
和 Address
将扩展它。所以它是一个 TABLE_PER_CLASS 策略。我假设我可以将其用作 entity
字段的类型,尽管我不确定。但是,我担心这可能会严重影响性能,因为 JPA 需要查询许多表才能找到实际实例。
第二种是简单地使用@MappedSuperClass
并将实体的UUID 存储在MutationEntityLink
的entity
字段中。为了获得具有该 UUID 的实际实体,我必须以编程方式解决它。添加一个带有实体类名的附加列,或其他允许我识别它或将其粘贴到 JPQL 查询中的东西就可以了。这需要更多的工作,但似乎更有效率。如果需要,我不反对编写一些实用程序类或进行一些反射/自定义注释工作。
我的问题是这些方法中哪一个看起来最好?或者,您可能有更好的建议,或者注意到我遗漏了什么;例如,也许有一种方法可以添加类型列,即使使用 TABLE_PER_CLASS 继承也可以将 JPA 指向正确的表?也许您已经尝试过这样的事情,并想警告我可能会出现的许多问题。
一些附加信息:
- 我们创建了数据库架构,因此我们可以添加任何我们想要的内容。
- 单表继承策略不是一种选择。这些表必须保持不同。出于同样的原因,联合继承似乎也不合适。
- JPA 提供程序是 Hibernate,使用不属于 JPA 标准的东西不是问题。
最佳答案
如果实体除了具有 uuid 之外没有任何共同点,我会使用您描述的第二种方法:使用 MappedSuperclass
。使公共(public)父类(super class)成为实体会阻止您在需要时使用不同的继承策略,即使不存在实例,也需要为该超实体创建一个表,从业务角度来看,这是错误的。
链接本身可以通过多种方式实现,例如您可以为每个要映射的实体(例如 CustomerMutationEntityLink
等)子类化 MutationEntityLink
或按照您的描述进行操作,即仅存储 uuid 以及一些鉴别器/类型信息和以编程方式解决(顺便说一句,我们正在使用这种方法来处理类似的事情。)。
关于java - 在 JPA 中链接不同实体类型的最佳方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36307706/