根据 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
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个表:A,BB,和CC。双方BB并CC应称为默认鉴别列DTYPE。它们还应提供所有映射属性及其各自子类的关联所必需的所有列。
A
BB
CC
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>
您可以通过映射整个嵌套继承层次 <union-subclass>,<sub- class>以及<joined- subclass>映射元素。您不能将它们混合使用-例如,要从带有区分符的每类表层次结构切换到规范化的每子类表策略。 一旦决定了继承策略,就必须坚持下去 。
<union-subclass>
<sub- class>
<joined- subclass>
但是,这并非完全正确。使用一些Hibernate技巧,您可以切换特定子类的映射策略。例如, 您可以将类层次结构映射到单个表,但是对于特定的子类,请使用外键映射策略切换到单独的表 ,就像每个子类的表一样。使用<join>mapping元素可以实现:
<join>
<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; ... }
Java Persistence还支持带有注释的混合继承映射策略。像以前一样,BillingDetails用映射超类InheritanceType.SINGLE_TABLE。现在,将要从单个表中分解出来的子类映射到辅助表。
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; ... }
我没有对此进行测试,但是您可以尝试:
@SecondaryTable
我尚未对此进行测试,不知道它是否适合BB1,BB2。