3.多對多(在多對多的使用上,建議使用表間關聯方式,使用外鍵關聯冗餘數據較爲嚴重)
1.1多對多外鍵關聯
Test和SubTest的id爲auto_increment
Test.class
@OneToMany(cascade=CascadeType.ALL,fetch=FetchType.EAGER)
@JoinColumn(name="eee")
public List<SubTest> subtests;
@OneToMany(fetch=FetchType.EAGER,cascade=CascadeType.ALL)
@JoinColumn(name="ddd") //默認不填JoinColumn會自動生成一個外鍵字段
private List<Test> tests;
多對多的外鍵關聯在兩者間都採用OnetoMany的標籤註解,然後使用JoinColumn。
1.2多對多表間關聯
Test和SubTest的id爲auto_increment
Test
@ManyToMany(cascade=CascadeType.ALL,fetch=FetchType.EAGER)
@JoinTable(name="dog",joinColumns = {@JoinColumn(name="abc")},
inverseJoinColumns =@JoinColumn(name = "bcd"))
public List<SubTest> subtests;
SubTest
@ManyToMany(fetch=FetchType.EAGER,cascade=CascadeType.ALL)
@JoinTable(name="dog",joinColumns = {@JoinColumn(name="bcd")},
inverseJoinColumns = { @JoinColumn(name= "abc")} )
private List<Test> tests;
對於多對多的表間關聯,我建議使用JoinTable的方式,因爲mappedBy的情況只支持單方面的,只能對一方使用mappedby,這意味着在對一方進行save數據的時候,關聯表不會進行insert操作。而JoinTable的情況則都能行得通。並且在生成關係表dog的時候,由於兩方地位同等,bcd和abc字段均只有外鍵關聯(如果是一對多的情況產生的關係表,會有多的一方即bcd字段設置成爲主鍵,產生的後果自己去思考)。
綜合上述幾種配置,當我們在考慮一對一的情況下應當使用主鍵關聯,一對多的情況在外鍵關聯和表間關聯都可做選擇,如果使用外鍵關聯,則對於Test對象添加的list數據,不應當重複add相同的SubTest對象,因爲hibernate只會當做一條數據來進行插入,如果確實是Test所擁有的SubTest對象有相同的情況,應該先new再add。這是外鍵關聯不好的地方,也因此,在SubTest表中會出現冗餘的數據(多個相同對象包含的外鍵不同而已)。而如果使用表間關聯,則list可對同一個SubTest對相進行重複添加,而在處理上不會再SubTest表上insert多條數據,只會在關係表上insert多條數據。然而在一對多的情況下建立表間關聯,當我們使用JoinTable的時候,因爲通常hibernate在建表時會要求有主鍵,因此在關係表上bcd字段(SubTest的外鍵約束字段)爲主鍵,就無法產生相同的數據。這是一個問題。目前我還在測試當中。多對多的情況,我會建議使用表間關聯,因爲外鍵關聯的冗餘數據問題比較嚴重。(特殊情況可考慮外鍵關聯)