Hibernate對映類繼承之每個帶有隱式多型的具體類一張表(每個子類各一張表,有各自的對映檔案)
阿新 • • 發佈:2019-02-15
Hibernate對映類繼承之每個帶有隱式多型的具體類一張表(每個子類各一張表)
我們可以準確地給每個子類使用一張表。子類的所有屬性,包括被繼承的屬性,都可以被對映到這張表的列。如圖:
CreditCard子類 -----> CreditCard.hbm.xml -----> CREDIT_CARD表
BillingDetails父類---->
BankAccount子類 -----> BankAccount.hbm.xml -----> BANK_ACCOUNT表
在Hibernate中你不必做任何特別的事來啟用多型行為。對CreditCard和BankAccount的對映很簡單,各自都在自己的實體<class>元素中,就像我們已經沒有基類的類所做的那樣。Hibernate仍然知道這個基類或者介面,因為它在啟動時掃描持久化類。這種方法的主要問題在於,它不太支援多型關聯。在資料庫中,關聯通常被表示為外來鍵關係。如果子類全部被對映到不同的表,對它們基類(本例BillingDetails)的多型關聯就無法被表示為一個簡單的外來鍵關係。這在我們的領域模型中會有問題,如果BillingDetails與一個存在的user關聯,兩張子類表都需要一個對User表的外來鍵引用。或者,如果User與BillingDetails有個多對一的關係,USER表就需要單個的外來鍵列,它必須同時引用兩個具體的子類表。這用一般的外來鍵約束是不可能的。
多型查詢(它返回與被查詢類的介面相匹配的所有類的物件)也有問題。針對基類的查詢必須作為幾個SQL SELECT執行,每個具體的子類一個。對於針對BillingDetails類的查詢,hibernate使用下列SQL:
select CREDIT_CARD_ID,OWNER,NUMBER,EXP_MONTH,EXP_YEAR... from CREDIT_CARD;
select BANK_ACCOUNT_ID,OWNER,ACCOUNT,BANKNAME,... from BANK_ACCOUNT;
注意每個具體的子類都需要一個單獨的查詢。
這種對映策略進一步的概念問題在於,幾張不同表的幾個不同的列具有完全相同的語義。這使得模式演變更為複雜。例如,對一個基類屬性的改變導致了多個列的變化。它也使得把應用到所有子類的資料庫完整性約束實現起來變得更加困難。
我們推薦這種方法(僅僅)用於類層次結構的最頂層,那裡通常不需要多型,且未來也不太可能修改基類。
pom.xml:
hibernate.cfg.xml:
父類,BillingDetails.java:
子類,BankAccount.java:
子類的對映,BankAccount.hbm.xml:
子類,CreditCard.java:
子類對映,CreditCard.hbm.xml:
util/HibernateUtil.java:
util/Manager.java:
輸出sql與日誌:
注意,這裡有兩張表:CREDIT_CARD , BANK_ACCOUNT.
CREDIT_CARD表:
CREDIT_CARD_ID
OWNER
NUMBER
EXP_MONTH
EXP_YEAR
BANK_ACCOUNT表:
BANK_ACCOUNT_ID
OWNER
ACCOUNT
BANKNAME
SWIFT