如何将继承策略与 JPA 注释和 Hibernate 混合使用? [英] How to mix inheritance strategies with JPA annotations and Hibernate?
问题描述
根据Hibernate 参考文档,在使用 Hibernate 的 XML-Metadata 时应该可以混合不同的继承映射策略:
http://docs.jboss.org/hibernate/stable/core/reference/en/html/inheritance.html#inheritance-mixing-tableperclass-tablepersubclass
According to the Hibernate Reference Documentation it should be possible to mix different inheritance mapping strategies when using Hibernate's XML-Metadata:
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
However, the corresponding section of the Hibernate Annotations Reference Guide does not cover that:
http://docs.jboss.org/hibernate/stable/annotations/reference/en/html/entity.html#d0e1168
另一方面,JavaDocs 建议混合继承策略应该是可能的.例如在 javax.persistence.DiscriminatorColumn 它说:
On the other hand, the JavaDocs suggest that mixing inheritance strategies should be possible. For instance in javax.persistence.DiscriminatorColumn it says:
策略和鉴别器列仅在实体类层次结构或应用不同继承策略的子层次结构的根中指定.
The strategy and the discriminator column are only specified in the root of an entity class hierarchy or subhierarchy in which a different inheritance strategy is applied.
<小时>
以下是我试图实现的映射示例.我想在层次结构的根附近使用 table-per-subclass 映射,但在叶子附近更改为 table-per-class-hierarchy 映射.下面是一些示例代码:
The following is an example for the mapping I'm trying to achieve. I'd like to use table-per-subclass mapping near the root of the hierarchy, but change to table-per-class-hierarchy mapping near the leaves. Here's some example code:
@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
的默认鉴别器列.它们还应提供所有映射属性和它们各自子类的关联所需的所有列.
What I expect from this mapping is having exactly 3 tables: A
, BB
, and CC
. Both BB
and CC
should have a default discriminator column called DTYPE
. They should also provide all columns necessary for all mapped properties and associations of their respective subclasses.
相反,类层次结构似乎始终使用table-per-subclass 继承策略.IE.我为上面提到的每个实体都有一个自己的表.我想避免这种情况,因为类层次结构的叶子非常轻量级,并且为每个叶子设置一个单独的表似乎有点过分!
Instead , the class hierarchy seems to use the table-per-subclass inheritance strategy throughout. I.e. I get an own table for each of the entities mentioned above. I'd like to avoid this, since the leaves of the class-hierarchy are extremely light-weight and it just seems overkill to have a separate table for each of them!
我是不是忽略了什么?任何建议都非常感谢!我很乐意提供更多信息...
Did I overlook something? Any advice is highly appreciated! I'll be glad to provide additional info...
推荐答案
根据 Hibernate 参考文档,在使用 Hibernate 的 XML-Metadata (...) 时应该可以混合不同的继承映射策略
According to the Hibernate Reference Documentation it should be possible to mix different inheritance mapping strategies when using Hibernate's XML-Metadata (...)
实际上,它真的不受支持,他们正在欺骗"使用辅助表从文档示例中的单表策略切换.引用Java Persistence with Hibernate:
Actually, it's not really supported, they are "cheating" using a secondary table to switch from the single table strategy in the example of the documentation. Quoting Java Persistence with Hibernate:
您可以映射整个继承嵌套层次结构
,
,和
映射元素.你不能混合它们——因为例如,从一个每个类的表层次结构归一化的鉴别器每个子类的表策略.一次你已经做出了一个决定继承策略,你必须坚持下去.
You can map whole inheritance hierarchies by nesting
<union-subclass>
,<sub- class>
, and<joined-subclass>
mapping elements. You can’t mix them — for example, to switch from a table-per-class hierarchy with a discriminator to a normalized table-per-subclass strategy. Once you’ve made a decision for an inheritance strategy, you have to stick to it.
然而,这并不完全正确.使用一些 Hibernate 技巧,您可以切换映射策略特定的子类.例如,你可以将类层次结构映射到单个表,但对于特定的子类,切换到一个单独的表外键映射策略,就像每个子类都有表.这是可以使用
映射元素:
This isn’t completely true, however.
With some Hibernate tricks, you can
switch the mapping strategy for a
particular subclass. For example, you
can map a class hierarchy to a single
table, but for a particular subclass,
switch to a separate table with a
foreign key mapping strategy, just as
with table per subclass. This is
possible with the <join>
mapping
element:
<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>
您可以通过注释实现相同的效果:
And you could achieve the same with annotations:
Java Persistence 也支持这种带有注解的混合继承映射策略.像之前一样,将超类 BillingDetails
与 InheritanceType.SINGLE_TABLE
映射.现在将要从单个表中分离出来的子类映射到辅助表.
Java Persistence also supports this mixed inheritance mapping strategy with annotations. Map the superclass
BillingDetails
withInheritanceType.SINGLE_TABLE
, as you did before. Now map the subclass you want to break out of the single table to a secondary 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;
...
}
我没有对此进行测试,但您可以尝试:
I didn't test this but you could maybe try to:
- 使用 SINGLE_TABLE 策略映射 A
- 使用
@SecondaryTable
注释映射 BB、CC 等.
- map A using a SINGLE_TABLE strategy
- map BB, CC, etc using the
@SecondaryTable
annotation.
我没有测试过这个,我不知道它是否适用于 BB1、BB2.
I've not tested this, I don't know if it will work well for BB1, BB2.
- Java 持久化与 Hibernate
- 5.1.5 混合继承策略 (p207-p210)
这篇关于如何将继承策略与 JPA 注释和 Hibernate 混合使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!