Краткое изложение проблемы
Hibernate предполагает, что всякий раз, когда кто-то использует подкласс, все столбцы должны быть созданы в верхнем корне иерархии классов, независимо от того, какое имя таблицы было предоставлено. Может кто-то объяснить, почему за этим стоит и если есть способ обойти этот код и как-то избежать создания invoice_id в таблице транзакций ???
Подробнее
У меня очень глубокая иерархия классов в моей доменной модели, и я хочу использовать тег дискриминатора для поддержки наследования.
Изначально я отобразил свои классы с помощью join-subclass, однако используемые таблицы содержат сотни тысяч записей, и это оказывается узким местом в производительности. По сути, я хочу сгладить структуру таблицы, не касаясь области, и поэтому мы перешли к тегу дискриминатора.
Мои отображения в режиме гибернации выглядят так (удалили дополнительный столбец для простоты)
Транзакция Отображение
<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 создает столбец "invoice_id" в таблице транзакций (это неправильно), а также в billing_transaction (это правильно). При дальнейшей отладке я нашел некоторые интересные результаты, и мне нужны отзывы / советы.
Hibernate создает столбец invoice_id в billing_transaction, что я и хочу.
Hibernate также создает еще один столбец с тем же именем, то есть invoice_id в таблице транзакций, что не то, что я хочу.
Теперь это расстраивает. Несмотря на то, что я упомянул имя таблицы (Billing_Transaction) в invoice.hbm и установил inverse = "true", все же hibernate идет вперед и создает столбец 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 в таблице транзакций ???