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

时间:2016-03-30 11:38:26

标签: java hibernate jpa inheritance orm

仓促的

短版

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

  • 使用抽象实体和TABLE_PER_CLASS策略,或
  • 使用@MappedSuperClass存储链接表中实例的类名,或类似的东西,让我定义逻辑以从右表中获取实际实例。

两者在复杂性和性能方面都有优点和缺点。您认为最好的是哪种,是否有第三种选择,或者您过去曾尝试过这样的事情并建议/强烈警告?

长版,以防您需要更多背景资料:

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

将以下具有UUID的实体作为(极简化)示例: mutable entities

要存储“突变”,我们使用名为MutationHolder的表/实体。要将变异链接到其目标实体,需要MutationEntityLink。这个数据不直接在MutationHolder上的唯一原因是因为可以有直接或间接的链接,但这在这里并不重要,所以我把它排除在外: mutation entities

问题归结为我如何为entity中的MutationEntityLink字段建模。我能想到两种方法。

第一个是使用UUID字段创建一个抽象的@Entity带注释的类。 CustomerContractAddress会扩展它。所以这是一个TABLE_PER_CLASS策略。我假设我可以将它用作entity字段的类型,尽管我不确定。但是,我担心这可能会造成严重的性能损失,因为JPA需要查询许多表来查找实际的实例。

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

我的问题是哪种方法看起来最好?或者,您可能有更好的建议,或者注意到我遗漏了一些东西;例如,也许有一种方法来添加一个类型列,即使使用TABLE_PER_CLASS继承将JPA指向右表?也许你已经尝试过这样的事情并且想要警告我可能出现的许多问题。

其他一些信息:

  • 我们创建了数据库模式,因此我们可以添加任何我们想要的内容。
  • 单表继承策略不是一种选择。表必须保持不同。出于同样的原因,联合继承似乎也不合适。
  • JPA提供程序是Hibernate,并且使用不属于JPA标准的内容不是问题。

2 个答案:

答案 0 :(得分:6)

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

链接本身可以以多种方式实现,例如您可以为每个要映射的实体(例如MutationEntityLink等)创建子类CustomerMutationEntityLink,或按照您的描述进行操作,即仅存储uuid以及一些鉴别器/类型信息并以编程方式解析(我们是使用这种方法来获得类似的东西。)

答案 1 :(得分:2)

在继承关联/方法/属性时需要使用{ "s": 2, "s,b": 1 } ,而在拥有实体和子实体时通常使用TABLE_PER_CLASS。如果存在与模型中的基类关联的实体,则使用TABLE_PER_CLASS,因为基类的行为类似于实体。否则,由于基类将包括对彼此不相关的实体通用的属性/属性和方法,因此使用@MappedSuperclass将是一个更好的主意

示例1:您需要为某些不同的活动设置闹钟,例如"吃药","打电话给妈妈","去看医生&#34 34;警报信息的内容无关紧要,您需要提醒。所以使用TABLE_PER_CLASS因为报警消息,这是你的基类就像这里的一个实体。

示例2:假设基类AbstractDomainObject允许您为没有实体与基类关联的每个对象创建登录ID,loginName,创建/修改日期,您需要指定协会为了以后清算,例如"公司","大学"在这种情况下,使用@MappedSuperclass会更好。