Hibernate關(guān)系映射3:雙向1-1關(guān)聯(lián)

2018-09-28 14:19 更新

我最近在復(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)


雙向1-1關(guān)聯(lián)需要修改兩邊的持久化類代碼,讓兩個持久化類都增加引用關(guān)聯(lián)實(shí)體的屬性,并為該屬性提供get和set方法。

雙向1-1關(guān)聯(lián)有三種映射模式:

  • 基于主鍵
  • 基于外鍵
  • 使用連接表

在該文中,將主要介紹前兩種模式。

域模型

圖1

關(guān)系數(shù)據(jù)模型

按照外鍵映射

圖2

按照主鍵映射

圖3

基于外鍵


介紹

對于基于外鍵的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)系,兩個實(shí)體原本處于平等狀態(tài),但當(dāng)我們選擇任意一個表來增加外鍵后(增加<many-to-one.../>元素的實(shí)體端),該表即變成從表,而另一個表則成為主表。

另一端需要使用<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);
    }

Notice

上面的映射策略可以互換,即讓Manager存放外鍵,使用<many-to-one.../>元素映射關(guān)聯(lián)屬性;但Department端則必須使用<one-to-one.../>元素映射,萬萬不可兩邊都使用相同的元素映射關(guān)聯(lián)屬性。

基于主鍵


介紹

如果采用基于主鍵的映射策略,則一端的主鍵生成器需要使用foreign策略,表明將根據(jù)對方的主鍵來生成自己的主鍵,本實(shí)體不能擁有自己的主鍵聲稱策略。<param>子元素指定使用當(dāng)前持久化類的哪個屬性作為“對方”。

<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ù)庫表的主鍵添加一個外鍵約束,引用被關(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>
以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號