我最近在復(fù)習(xí)一下關(guān)于Hibernate關(guān)系映射的知識,看了書本的介紹以及視頻。這幾篇博客都是對學(xué)到知識的一點(diǎn)總結(jié)。當(dāng)然,這些這是最基本的能夠?qū)崿F(xiàn)關(guān)聯(lián)關(guān)系的配置,在實(shí)際的使用中,還有很多參數(shù)需要根據(jù)情況來設(shè)置。但也算是對以后開發(fā)過程中遇到遺忘的地方可以進(jìn)行查閱。
在本文中使用的Demo也都已經(jīng)上傳到github中,里邊有詳細(xì)的運(yùn)行說明。Github地址:HibernateRelationMapping
雙向1-1關(guān)聯(lián)需要修改兩邊的持久化類代碼,讓兩個(gè)持久化類都增加引用關(guān)聯(lián)實(shí)體的屬性,并為該屬性提供get和set方法。
雙向1-1關(guān)聯(lián)有三種映射模式:
在該文中,將主要介紹前兩種模式。
對于基于外鍵的1-1關(guān)聯(lián),外鍵可以存放在任意一邊。需要存放外鍵的一端,需要增加<many-to-one.../>
元素,并且為<many-to-one.../>
元素增加unique="true"
屬性來表示該實(shí)體實(shí)際上是1的一端。<many-to-one name="manager" class="Manager" column="MGR_ID" unique="true"></many-to-one>
對于1-1的關(guān)聯(lián)關(guān)系,兩個(gè)實(shí)體原本處于平等狀態(tài),但當(dāng)我們選擇任意一個(gè)表來增加外鍵后(增加<many-to-one.../>
元素的實(shí)體端),該表即變成從表,而另一個(gè)表則成為主表。
另一端需要使用<one-to-one.../>
元素,該<one-to-one.../>
元素需要使用name屬性指定關(guān)聯(lián)屬性名。為了讓系統(tǒng)不再為本表增加一列,而是使用外鍵關(guān)聯(lián),使用property-ref
屬性指定引用關(guān)聯(lián)類的屬性。<one-to-one name="department" class="Department" property-ref="manager"></one-to-one>
實(shí)體類
public class Department {
private Integer deptId;
private String deptName;
private Manager manager;
//省去get和set
}
public class Manager {
private Integer mgrId;
private String mgrName;
private Department department;
//省去get和set
}
Manager.hbm.xml
<hibernate-mapping package="com.lihui.hibernate.double_1_1.foreign">
<class name="Manager" table="MANAGERS">
<id name="mgrId" type="java.lang.Integer">
<column name="MGR_ID" />
<generator class="native" />
</id>
<property name="mgrName" type="java.lang.String">
<column name="MGR_NAME" />
</property>
<!-- 映射1-1的關(guān)聯(lián)關(guān)系,在對應(yīng)的數(shù)據(jù)表中已經(jīng)有外鍵,當(dāng)前持久花類使用ont-to-one進(jìn)行映射 -->
<one-to-one name="department" class="Department" property-ref="manager"></one-to-one>
</class>
</hibernate-mapping>
Department.hbm.xml
<hibernate-mapping package="com.lihui.hibernate.double_1_1.foreign">
<class name="Department" table="DEPARTMENTS">
<id name="deptId" type="java.lang.Integer">
<column name="DEPT_ID" />
<generator class="native" />
</id>
<property name="deptName" type="java.lang.String">
<column name="DEPT_NAME" />
</property>
<many-to-one name="manager" class="Manager" column="MGR_ID" unique="true"></many-to-one>
</class>
</hibernate-mapping>
測試
@Test
public void testGet(){
Department dep = (Department) session.get(Department.class, 1);
System.out.println(dep.getDeptName());
Manager mgr =dep.getManager();
System.out.println(mgr.getMgrName());
}
@Test
public void testSave() {
Department dep = new Department();
dep.setDeptName("a");
Manager mgr = new Manager();
mgr.setMgrName("b");
dep.setManager(mgr);
mgr.setDepartment(dep);
session.save(mgr);
session.save(dep);
}
上面的映射策略可以互換,即讓Manager存放外鍵,使用<many-to-one.../>
元素映射關(guān)聯(lián)屬性;但Department端則必須使用<one-to-one.../>
元素映射,萬萬不可兩邊都使用相同的元素映射關(guān)聯(lián)屬性。
如果采用基于主鍵的映射策略,則一端的主鍵生成器需要使用foreign策略,表明將根據(jù)對方的主鍵來生成自己的主鍵,本實(shí)體不能擁有自己的主鍵聲稱策略。<param>
子元素指定使用當(dāng)前持久化類的哪個(gè)屬性作為“對方”。
<generator class="foreign" >
<param name="property">manager</param>
</generator>
當(dāng)然,任意一端都可以采用foreign主鍵生成器策略,表明將根據(jù)對方主鍵來生成自己的主鍵。
采用foreign主鍵生成器策略的一端增加one-to-one元素映射相關(guān)屬性,其ont-to-one屬性還應(yīng)增加constrained=true
屬性;另一端增加one-to-one元素映射關(guān)聯(lián)屬性。
constrained:指定為當(dāng)前持久化類對應(yīng)的數(shù)據(jù)庫表的主鍵添加一個(gè)外鍵約束,引用被關(guān)聯(lián)對象所對應(yīng)的數(shù)據(jù)庫主鍵。
實(shí)體類與上文中的實(shí)體類相同。
Manager.hbm.xml
<hibernate-mapping package="com.lihui.hibernate.double_1_1.primary">
<class name="Manager" table="MANAGERS">
<id name="mgrId" type="java.lang.Integer">
<column name="MGR_ID" />
<generator class="native" />
</id>
<property name="mgrName" type="java.lang.String">
<column name="MGR_NAME" />
</property>
<one-to-one name="department" class="Department"></one-to-one>
</class>
</hibernate-mapping>
Department.hbm.xml
<hibernate-mapping package="com.lihui.hibernate.double_1_1.primary">
<class name="Department" table="DEPARTMENTS">
<id name="deptId" type="java.lang.Integer">
<column name="DEPT_ID" />
<generator class="foreign" >
<param name="property">manager</param>
</generator>
</id>
<property name="deptName" type="java.lang.String">
<column name="DEPT_NAME" />
</property>
<one-to-one name="manager" class="Manager" constrained="true"></one-to-one>
</class>
</hibernate-mapping>
更多建議: