我正在試驗Hibernate以獲得經驗。我創建了一個類Person
有兩個子類:Student
和Worker
:Hibernate:這個映射到外鍵上的子類的映射有什麼問題?
public abstract class Person {
private Long id;
...
}
public class Student extends Person { ... }
另一類,Employer
,有Worker
雙向一個一對多的關係。
public class Worker extends Person {
private Employer employer;
...
}
public class Employer {
private String taxId;
private Set<Worker> employees = new HashSet<Worker>();
...
}
該映射是
<class name="Employer" table="EMPLOYER">
<id name="taxId" column="TAX_ID" length="11">
<generator class="assigned"/>
</id>
...
<set name="employees" inverse="true">
<key column="EMPLOYER_TAX_ID"/>
<one-to-many class="Worker"/>
</set>
</class>
繼承層次結構被建模與混合策略,其中Student
映射到PERSON
表,但Worker
被存儲在它自己的表,加入用外鍵:
<class name="Person" table="PERSON">
<id name="id" column="PERSON_ID" type="long" unsaved-value="0">
<generator class="native"/>
</id>
<discriminator column="PERSON_TYPE" type="string"/>
...
<subclass name="Student" discriminator-value="STU"> ... </subclass>
<subclass name="Worker" discriminator-value="WRK">
<join table="WORKER">
<key column="WORKER_ID"/>
<many-to-one name="employer" column="EMPLOYER_TAX_ID" cascade="save-update"/>
...
</join>
</subclass>
</class>
我使用Apache Derby 10.5.3.0並通過設置自動生成模式0至create-drop
。
爲了測試這一切,我創建了下面的數據集DBUnit的測試:
<EMPLOYER TAX_ID = "1234567890"
...
/>
<PERSON PERSON_ID = "12345"
PERSON_TYPE = "WRK"
...
/>
<WORKER WORKER_ID = "12345"
EMPLOYER_TAX_ID = "1234567890"
...
/>
我有它加載的工人實體並驗證它是否具有正確的員工進行測試。這通過。然後,對於相反方向上的測試:
String taxId = "1234567890";
Employer employer = (Employer) session.get(Employer.class, taxId);
assertNotNull(employer);
assertThat(employer.getEmployees().size(), is(1));
在執行時,最後的斷言失敗,因爲組僱員爲空。
進一步挖掘,我發現,由於某些原因休眠表人看起來(並創建)的EMPLOYER_TAX_ID列,而不是WORKER的!它也存在於WORKER中,但該查詢中沒有使用它。用於填寫員工組的選擇語句爲:
select
employees0_.EMPLOYER_TAX_ID as EMPLOYER10_1_,
employees0_.PERSON_ID as PERSON1_1_,
employees0_.PERSON_ID as PERSON1_1_0_,
employees0_.FIRST_NAME as FIRST3_1_0_,
employees0_.FAMILY_NAME as FAMILY4_1_0_,
employees0_.DATE_OF_BIRTH as DATE5_1_0_,
employees0_.HOME_ADDRESS as HOME6_1_0_,
employees0_.CITY as CITY1_0_,
employees0_.ZIP as ZIP1_0_,
employees0_1_.EMPLOYER_TAX_ID as EMPLOYER2_2_0_,
employees0_1_.JOB_TITLE as JOB3_2_0_,
employees0_1_.JOB_GRADE as JOB4_2_0_,
employees0_1_.START_DATE as START5_2_0_
from
PERSON employees0_
inner join
WORKER employees0_1_
on employees0_.PERSON_ID=employees0_1_.WORKER_ID
where
employees0_.EMPLOYER_TAX_ID=?
這是爲什麼? 我怎樣才能讓Hibernate在WORKER表中找到EMPLOYER_TAX_ID?
請注意,由於這是一個實驗項目,我可以改變任何事情。我讚賞任何解決方法,但我更願意瞭解正在進行的操作並儘可能修復此映射(儘可能)。
更新:如果我切換到一個乾淨的<joined-subclass>
繼承映射策略,生成的模式看起來應該和測試通過。這是一個很好的解決方法,但我仍然好奇是否有辦法讓混合策略能夠正常工作。
如果您可以使用JPA批註,爲什麼還要使用那些討厭的XML文件? – Kdeveloper 2010-04-12 12:43:33
@Kdeveloper我們真正的項目使用XML,因此這是我的主要目標。但我會將我的寵物項目擴展到未來的註釋,因爲時間允許... – 2010-04-12 12:55:11
僅供以後參考,將使用註釋定義一對多雙向關係,如下所示: '@OneToMany(mappedBy =「nameOfSingleInstanceInOtherEntity 「)',\t'@ManyToOne @JoinColumn(name =」nameWhichYouWishToGiveToIdField「)' – 2010-04-12 14:52:54