【发布时间】:2010-10-05 13:11:08
【问题描述】:
问题的简短摘要
Hibernate 假设每当有人使用子类时,所有列都应该在类层次结构的顶部根中创建,而不管提供了什么表名。 有人可以解释一下它背后的原因吗如果有办法绕过此代码并以某种方式避免在事务表中创建 invoice_id ???
详情
我的域模型中有一个非常深的类层次结构,并希望使用鉴别标记来支持继承。
最初我使用连接子类映射我的类,但是所涉及的表有数十万条记录,结果证明这是一个性能瓶颈。所以本质上我想在不触及域的情况下扁平化我的表结构,这就是我们转向鉴别器标签的原因。
我的休眠映射看起来像(为简单起见删除了额外的列)
交易映射
<class name="Transaction" table="transaction" abstract="true">
...
<discriminator column="transaction_type" type="string"/>
</class>
CashBasedTrsansaction映射
<subclass name="CashBasedTransaction" extends="Transaction" discriminator-value="CASH">
<join table="cash_based_transaction">
<key column="id" />
</join>
<subclass discriminator-value="BILLING" name="BillingTransaction">
<join table="billing_transaction">
<key column="id" />
<many-to-one name="invoice" column="invoice_id" cascade="all" access="field" lazy="false">
</many-to-one>
</join>
<subclass name="ChildBillingTransaction" discriminator-value="UPT">
<join table="billing_transaction">
<key column="id" />
...
</join>
</subclass>
<subclass abstract="true" name="AnotherChildOfBillingTransaction" discriminator-value="LPT">
<subclass name="SuperChildOfBillingTransaction" discriminator-value="OCLPT">
<join table="billing_transaction">
<key column="id" />
...
</join>
</subclass>
<subclass name="AnoherSuperChildOfBillingTransaction" discriminator-value="SLPT">
<join table="billing_transaction">
<key column="id" />
...
</join>
</subclass>
</subclass><!--End Of AnotherChildOfBillingTransaction-->
</subclass><!--End Of BillingTransaction-->
</subclass><!--End Of CashBasedTransaction-->
发票映射
<class name="Invoice" table="invoice">
...
<bag name="billingTransactions" access="field" cascade="all" inverse="true" table="billing_transaction">
<key column="invoice_id" />
<one-to-many class="BillingTransaction" />
</bag>
</class>
我想要实现的目标:我想在 billing_transaction 之后展平表结构。换句话说,我希望数据库中只有三个表
- 交易
- cash_based_transaction
- billing_transaction(此表应在展平所有子类后包含所有列)
P.S:请注意,我不是从聚合根(读取事务)而是从我的类层次结构中的某处展开表结构,在这种情况下为 billing_transaction。
问题:Hibernate 正在事务表(这是错误的)和 billing_transaction(这是正确的)中创建一个列“invoice_id”。在进一步调试中,我发现了一些有趣的结果,需要一些反馈/建议。
Hibernate 在 billing_transaction 中创建了我想要的列 invoice_id。
Hibernate 还会在事务表中创建另一个具有相同名称的列,即 invoice_id,这不是我想要的。
现在这令人沮丧。即使我在 invoice.hbm 中提到了表名(Billing_Transaction)并设置了 inverse="true",但休眠继续并在事务表中创建列 invoice_id,即使 Billing_Transaction 中已经有一个列。我期待,因为我给它表名 hibernate 应该采用该名称并检查 billing_transaction 是否具有 invoice_id ......相反,hibernate 正在做完全相反的事情。它完全忽略了我提供的表名并接触到了最超级的类,即事务。当它发现不存在这样的列时,它会在那里创建 invoice_id 列。结果,我的表中有两个 invoice_id 列。一个在 billing_transaction 中我希望它存在的位置,另一个在我不希望它存在的事务表中。
我找到了导致它的代码。在 org.hibernate.mapping.Subclass 表中使用下面给出的代码标识
public Property getIdentifierProperty() {
return getSuperclass().getIdentifierProperty();
}
换句话说,hibernate 假设每当有人使用子类时,所有列都应该在类层次结构的顶级根中创建,而与提供的表名无关。有人可以解释一下吗?背后的推理以及是否有办法绕过此代码并以某种方式避免在事务表中创建 invoice_id ???
【问题讨论】:
-
如果问题不够清楚请告诉我???我将尝试进一步详细说明......我在这个论坛上听到了很多关于非常迅速的回复,不幸的是到目前为止,回复非常温暖......
标签: hibernate