当前位置: 首页 > 面试题库 >

如何将继承策略与JPA批注和Hibernate混合使用?

孟彦
2023-03-14
问题内容

根据 Hibernate参考文档
,使用Hibernate的XML元数据时应该可以混合使用不同的继承映射策略:http :
//docs.jboss.org/hibernate/stable/core/reference/en/html/inheritance.html#inheritance
-mixing-tableperclass-
tablepersubclass

但是,《 Hibernate注释参考指南》 的相应部分并未涵盖以下内容:
http://docs.jboss.org/hibernate/stable/annotations/reference/en/html/entity.html#d0e1168

另一方面,JavaDocs建议混合继承策略应该可行。例如在javax.persistence.DiscriminatorColumn中,它说:

仅在应用 了不同继承策略 的实体类层次结构 或子 层次结构的根中指定策略和鉴别符列。

以下是我尝试实现的映射的示例。我想在层次结构的根附近使用 每个子类的表 映射,但是在叶子附近更改为 每个类的表 映射。这是一些示例代码:

@Entity
@Inheritance( strategy = InheritanceType.JOINED )
public abstract class A implements Serializable
{
    @Id
    private String id;

    // other mapped properties...
}

@Entity
@Inheritance( strategy = InheritanceType.SINGLE_TABLE )
public class BB extends A
{
    // other mapped properties and associations...
}

@Entity
public class BB1 extends BB
{
    // other stuff, not necessarily mapped...
}

@Entity
public class BB2 extends BB
{
    // other stuff, not necessarily mapped...
}

@Entity
@Inheritance( strategy = InheritanceType.SINGLE_TABLE )
public class CC extends A
{
    // other mapped properties and associations...
}

@Entity
public class CC1 extends CC
{
    // other stuff, not necessarily mapped...
}

...

我从这个映射想到的是恰好具有3个表:ABB,和CC。双方BBCC应称为默认鉴别列DTYPE。它们还应提供所有映射属性及其各自子类的关联所必需的所有列。

相反,类层次结构似乎始终使用 逐个表
继承策略。即我为上面提到的每个实体都有一个自己的表。我想避免这种情况,因为类层次结构的叶子非常轻巧,并且为每个人单独创建一张表似乎有点过分了!

我有事吗 任何建议都非常感谢!我很乐意提供其他信息…


问题答案:

根据Hibernate参考文档,使用Hibernate的XML元数据(…)时应该可以混合使用不同的继承映射策略。

实际上,它并没有得到 真正的 支持,他们使用辅助表“欺骗”了文档示例中的单表策略。 用Hibernate 引用 Java持久性

您可以通过映射整个嵌套继承层次 <union-subclass><sub- class>以及<joined- subclass>映射元素。您不能将它们混合使用-例如,要从带有区分符的每类表层次结构切换到规范化的每子类表策略。
一旦决定了继承策略,就必须坚持下去

但是,这并非完全正确。使用一些Hibernate技巧,您可以切换特定子类的映射策略。例如,
您可以将类层次结构映射到单个表,但是对于特定的子类,请使用外键映射策略切换到单独的表
,就像每个子类的表一样。使用<join>mapping元素可以实现:

<hibernate-mapping>
  <class name="BillingDetails"
      table="BILLING_DETAILS">

    <id>...</id>

    <discriminator
        column="BILLING_DETAILS_TYPE"
        type="string"/>
    ...
    <subclass
        name="CreditCard"
        discriminator-value="CC">
      <join table="CREDIT_CARD">
        <key column="CREDIT_CARD_ID"/>

        <property name="number" column="CC_NUMBER"/>
        <property name="expMonth" column="CC_EXP_MONTH"/>
        <property name="expYear" column="CC_EXP_YEAR"/>
        ...
      </join>
    </subclass>

    <subclass
        name="BankAccount"
        discriminator-value="BA">
      <property name=account" column="BA_ACCOUNT"/>
      ...
    </subclass>
  ...
  </class>
</hibernate-mapping>

您可以通过注释实现相同的目的:

Java
Persistence还支持带有注释的混合继承映射策略。像以前一样,BillingDetails用映射超类InheritanceType.SINGLE_TABLE。现在,将要从单个表中分解出来的子类映射到辅助表。

@Entity
@DiscriminatorValue("CC")
@SecondaryTable(
    name = "CREDIT_CARD",
    pkJoinColumns = @PrimaryKeyJoinColumn(name = "CREDIT_CARD_ID")
)
public class CreditCard extends BillingDetails {
    @Column(table = "CREDIT_CARD",
        name = "CC_NUMBER",
        nullable = false)
    private String number;
    ...
}

我没有对此进行测试,但是您可以尝试:

  • 使用SINGLE_TABLE策略的地图A
  • 使用@SecondaryTable注解映射BB,CC等。

我尚未对此进行测试,不知道它是否适合BB1,BB2。

参考

  • Java持久性与Hibernate
    • 5.1.5混合继承策略(p207-p210)


 类似资料:
  • 主要内容:连接策略示例在连接策略中,为每个实体类生成一个单独的表。 每个表的属性都与主键连接。 它消除了字段字重复的可能性。 以下语法表示连接的策略: - 连接策略示例 在这个例子中,我们将员工分为活跃员工和退休员工。 因此,子类和继承父类的和字段。 现在,按照以下步骤创建JPA项目 - 第1步: 在包下创建一个根实体类并指定所有必需的属性和注释。 文件:Employee.java - 第2步: 在包下创建实体类(它是

  • 主要内容:单表策略示例单表策略是定义继承实现的最简单有效的方法之一。 在这种方法中,多个实体类的实例仅作为属性存储在单个表中。 以下语法表示单个表策略 - 单表策略示例 在这个例子中,我们将员工分为活跃员工和退休员工。 因此,子类和继承父类的和字段。 现在,按照以下步骤创建JPA项目 - 第1步: 在包下创建一个根实体类并指定所有必需的属性和注释。 文件:Employee.java - 第2步: 在包下创建实体类(它是

  • 由于某些原因,我无法使Hibernate继承策略=InheritanceType.Joint&onetoMany的组合工作。以下是这些实体。 @实体

  • 主要内容:连接策略示例在按类表策略中,为每个子实体类生成一个单独的表。 与连接策略不同,在按类表策略中不会为父实体类生成单独的表。 以下语法表示按类表策略 - 连接策略示例 在这个例子中,我们将员工分为活跃员工和退休员工。 因此,子类和继承父类的和字段。 现在,按照以下步骤创建JPA项目 - 第1步: 在包下创建一个根实体类并指定所有必需的属性和注释。 文件:Employee.java - 第2步: 在包下创建实体类(

  • 我有一个实体照片映射在JPA/Hibernate,有三个不同的孩子(PhotoSpot,PhotoSecteur,PhotoVoie)。我使用了@继承(策略=继承类型。JOINED),一切工作正常的持久化方法,但我不能设法使其工作时,我想删除的照片之一。 我试图通过从父类中删除一个元素来删除一张照片,但我不知道这是否可行。我看了所有其他关于同一主题的帖子,我认为问题可能来自我的子实体有一个@man

  • 问题内容: 我正在考虑使用注释来定义我的Hibernate映射,但是遇到了一个问题:我想使用基础实体类来定义公共字段(包括ID字段),但是我希望不同的表具有不同的ID生成策略: 有什么办法可以做到这一点?我曾尝试将以下内容包含进来,但hibernate状态是我两次反对同一栏,这似乎是错误的: 问题答案: 在上面的代码中,您似乎在混合字段(超类)和方法(子类)的注释。Hibernate 参考文档建议