使用单表的休眠继承

Posted

技术标签:

【中文标题】使用单表的休眠继承【英文标题】:Hibernate inheritance using single table 【发布时间】:2011-11-19 14:29:24 【问题描述】:

在我们的系统中,我们存储订单。我们的项目中总是有客户特定的代码,但我们会尽可能地标准化。现在我正在使用 Hibernate 进行测试,看看我们是否可以使用它来改进我们的数据访问对象。我在理解 Hibernate 继承的可能性时遇到了一些问题。让我概述一下这个问题:

我们有 4 层软件:

    核心库 客户特定库(核心扩展) 应用程序(使用核心库和客户特定库的应用程序) 数据库

核心库

在核心库中,我们有以下关于订单的模型

    IOorder(接口) 顺序(类、核心顺序实现、默认实现)

假设订单具有以下默认字段:

身份证 CUSTOMER_NAME 订单日期 交货日期

客户特定库

在客户特定的库中,我们有以下关于订单的内容:

    CustomerOrder(类,订单扩展)。

现在订购我们系统的客户除了上述字段外,还希望存储国家和优先级。客户特定字段为:

国家 优先级

应用

应用程序通过工厂加载正确的 Order 类(Order 或 CustomerOrder)。工厂以某种方式知道是否有客户特定的实施。

数据库

在 de 数据库中,我们希望有 1 个表(出于性能原因),我们的核心/默认表(因此没有任何客户特定的扩展)如下所示:

create table ORDER
(
    OR_ID VARCHAR2(10) not null constraint OR_ID_PK primary key,
    OR_CUSTOMER_NAME VARCHAR2(20),
    OR_ORDER_DATE datetime,
    OR_DELIVERY_DATE datetime
);

对于需要额外两个字段的客户,我们将创建相同的表:

create table ORDER
(
    OR_ID VARCHAR2(10) not null constraint OR_ID_PK primary key,
    OR_CUSTOMER_NAME VARCHAR2(20),
    OR_ORDER_DATE datetime,
    OR_DELIVERY_DATE datetime,
    OR_COUNTRY VARCHAR2(20),
    OR_PRIORITY NUMBER
);

Java/休眠

现在我的问题是如何使用 Hibernate 仅使用 1 个表在 Java 中对此进行建模。核心 Order 实体不知道 CustomerOrder 中可用的任何额外列。我结合继承研究了 Hibernate 的一些选项,例如使用策略 InheritanceType.SINGLE_TABLE。但我相信这需要一个鉴别器列,而我没有。

Hibernate 有哪些选择?

【问题讨论】:

嗨长袍。您是直接使用 Hibernate,还是通过 JPA? 【参考方案1】:

我不知道我是否正确,但您似乎有两个继承 Order 的类 Order 和 CustomerOrder。如果这是真的,那么单表策略在没有任何配置的情况下非常适合,并且鉴别器列是类名,所以如果记录属于 Order 你将得到 Order in 作为鉴别器值,如果是 CustomerOrder 你将得到 CustomerOrder 作为鉴别器值。这是休眠的默认行为,您可以对其进行修改。

【讨论】:

接受了这个,因为它更关注我的问题,这似乎是对如何使用鉴别器的误解。【参考方案2】:

在这种情况下,您永远不会同时拥有两种实体(Order 和 CustomerOrder)。如果没有自定义,则只有 Orders,如果有自定义,则只有 CustomerOrders。

实际上,您可以假设您始终只有 CustomerOrder,但该类并不完全在您的控制之下,可以由客户提供的另一个类替换。

所以我可能会将 Order 设为 MappedSuperclass(即不构成实体但具有由实体继承的持久字段的类)。

在可由客户自定义的扩展 jar 中,我将定义 CustomerOrder 实体,该实体将仅扩展 Order 而不会添加任何其他字段。这个 CustomerOrder 类将以源代码的形式提供给客户,客户可以用他们自己的实现来替换它,并带有额外的字段。

【讨论】:

谢谢,我尝试了 MappedSuperclass on Order。但是,我不确定这在我的设置中是否有用。因为我还需要在核心库中有一个订单实体。使用 MappedSuperclass 我不会有一个核心实体(除非我当然做一个)。我认为我的主要问题是鉴别器。现在我更好地理解了它的用途。所以我在我的数据库表中添加了一个鉴别器列来让它工作。

以上是关于使用单表的休眠继承的主要内容,如果未能解决你的问题,请参考以下文章

我可以在休眠中使用单表继承从扩展实体中选择所有超级对象吗?

使用 SingleTable 进行休眠继承

在休眠中使用继承时如何仅获取一种实体?

如果不存在,休眠忽略列[关闭]

休眠:@EmbeddedId、继承和@SecondaryTable

我可以对未映射到表的实体使用休眠查询语言吗?