根据 Hibernate参考文档,在使用Hibernate的XML元数据时,应该可以混合使用不同的继承映射策略:
http://docs.jboss.org/hibernate/stable/core/reference/en/html/inheritance.html#inheritance-mixing-tableperclass-tablepersubclass
但是, Hibernate Annotations Reference Guide 的相应部分未涵盖以下内容:
http://docs.jboss.org/hibernate/stable/annotations/reference/en/html/entity.html#d0e1168
另一方面,JavaDocs建议混合继承策略应该是可能的。例如,在javax.persistence.DiscriminatorColumn中,它说:
策略和鉴别器列仅在实体类层次结构或子层次结构的根中指定,其中应用了不同的继承策略。
以下是我想要实现的映射的示例。我想在层次结构的根目录附近使用 table-per-subclass 映射,但是在叶子附近更改为 table-per-class-hierarchy 映射。这是一些示例代码:
@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
的默认鉴别器列。它们还应提供所有映射属性所需的所有列以及它们各自子类的关联。
相反,类层次结构似乎始终使用 table-per-subclass 继承策略。即我为上面提到的每个实体都有一个自己的表。我想避免这种情况,因为类层次结构的叶子非常轻,而且每个都有一个单独的表格似乎有点过分了!
我忽视了什么吗?任何建议都非常感谢!我很乐意提供更多信息......
答案 0 :(得分:27)
根据Hibernate参考文档,当使用Hibernate的XML-Metadata(...)时,应该可以混合不同的继承映射策略
实际上,它不是真正支持,他们使用辅助表来“欺骗”从文档示例中的单表策略切换。使用Hibernate引用 Java持久性:
您可以映射整个继承 嵌套的层次结构
<union-subclass>
,<sub- class>
, 和<joined-subclass>
映射 元素。你不能混合它们 - 因为 例如,从a切换 带有一个表的每个类的层次结构 鉴别器归一化 每子类表策略。的一旦 你做出了决定 继承策略,你必须 坚持下去。然而,这并非完全正确。 有了一些Hibernate技巧,你可以 切换a的映射策略 特殊的子类。例如,你 可以将类层次结构映射到单个层次结构 表,但对于特定的子类, 切换到一个单独的表与 外键映射策略,就像 每个子类的表。这是 可以使用
<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; ... }
我没有对此进行测试,但您可以尝试:
@SecondaryTable
注释映射BB,CC等。 我没有测试过这个,我不知道它是否适用于BB1,BB2。
答案 1 :(得分:24)
为了清楚起见,这里是Pascal的解决方案应用于我的问题中的示例代码:
@Entity
@Inheritance( strategy = InheritanceType.SINGLE_TABLE )
@DiscriminatorColumn( name = "entityType",
discriminatorType = DiscriminatorType.STRING )
public abstract class A implements Serializable
{
@Id
private String id;
// other mapped properties...
}
@Entity
@SecondaryTable( name = "BB" )
public class BB extends A
{
@Basic( optional = false)
@Column( table = "BB" )
private String property1;
// 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
@SecondaryTable( name = "CC" )
public class CC extends A
{
@ManyToOne( optional = false)
@JoinColumn( table = "CC" )
private SomeEntity association1;
// other mapped properties and associations...
}
@Entity
public class CC1 extends CC
{
// other stuff, not necessarily mapped...
}
...
我已经成功地将这种方法应用于我的问题,我将暂时坚持下去。但是我仍然看到以下缺点:
discriminator列位于层次结构的主表中,root-enity A
表。就我而言,在次要表BB
和CC
中设置鉴别器列就足够了。
无论何时向BB
或CC
的子类添加属性和关联,他/她都必须指定它们应映射到相应的辅助表。如果有办法使其成为默认值,那就太好了。