1. 程式人生 > >Hibernate的關聯關系映射

Hibernate的關聯關系映射

相對 odin map 以及 重復 pda blog ring 允許

系統設計的實體間關系分別為:一對一,一對多(多對一),多對多

一、一對多(多對一)

  一對多,多對一其實一樣,只是站在不同的角度看,這種情況在多的一方添加一的一方的主鍵為外鍵。以學生Student和班級Grade為例介紹一對多關聯關系在hibernate映射文件中的配置。

Student.hbm.xml映射文件配置(多的一方有外鍵)

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"
> <!-- Generated 2017-8-9 15:15:47 by Hibernate Tools 3.5.0.Final --> <hibernate-mapping> <class name="com.imooc.entity.Student" table="STUDENT"> <id name="sid" type="int"> <column name="SID" /> <generator class="increment" /> </
id> <property name="sname" type="java.lang.String"> <column name="SNAME" /> </property> <property name="sex" type="java.lang.String"> <column name="SEX" /> </property> <many-to-one name="grade" class
="com.imooc.entity.Grade" fetch="join"> <column name="gid" /> </many-to-one> </class> </hibernate-mapping>

Grade.hbm.xml映射文件配置

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2017-8-8 23:10:39 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping>
    <class name="com.imooc.entity.Grade" table="GRADE">
        <id name="gid" type="int">
            <column name="GID" />
            <generator class="increment" />
        </id>
        <property name="gname" type="java.lang.String">
            <column name="GNAME" />
        </property>
        <property name="gdesc" type="java.lang.String">
            <column name="GDESC" />
        </property>
        
        <!-- 一個班級對應多個學生,在班級映射文件中添加set屬性,設置inverse為true則一方Grade不再進行維護關聯信息(由多方維護)
            由於多方已知一方的信息,提高性能。設置級聯屬性cascade,則在保存班級信息會自動把學生信息(如果不存在)保存到數據庫中-->
        <set name="students" table="STUDENT" inverse="true" lazy="true" cascade="save-update">
            <key>
                <!-- 確定關聯的外鍵列 -->
                <column name="gid" />
            </key>
            <!-- 映射到關聯類的屬性 -->
            <one-to-many class="com.imooc.entity.Student" />
        </set>
    </class>
</hibernate-mapping>

二、一對一

  一對一其實是特殊的一對多關系,在任意一方引入對方的主鍵作為外鍵(實際使用非常少)。在映射文件中只需將多對一的unique設為true,以球隊與地址為例說明。

Address.hbm.xml映射文件配置

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.suxiaolei.hibernate.pojos.Adress" table="adress">
        <id name="id" type="integer">
            <column name="id"></column>
            <generator class="increment"></generator>
        </id>

        <property name="city" column="city" type="string"></property>
        
        <one-to-one name="team" class="com.suxiaolei.hibernate.pojos.Team" cascade="all"></one-to-one>

    </class>
</hibernate-mapping>

Team.hbm.xml映射文件配置(在many-to-one 加入unique=“true”,並且將Address的id作為外鍵)

<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.suxiaolei.hibernate.pojos.Team" table="team">
        <id name="id" type="integer">
            <column name="id"></column>
            <generator class="increment"></generator>
        </id>

        <property name="name" column="name" type="string"></property>
        
        <many-to-one name="adress" class="com.suxiaolei.hibernate.pojos.Adress" column="adress_id" unique="true"></many-to-one>

    </class>
</hibernate-mapping>

三、多對多

  多對多關系需要產生中間關系表,並引入兩張表的主鍵作為外鍵。以project和employee為例說明

project.hbm.xml映射文件配置

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2017-8-9 15:55:46 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping>
    <class name="com.imooc.entity.Project" table="PROJECT">
        <id name="proId" type="int">
            <column name="PROID" />
            <generator class="assigned" />
        </id>
        <property name="proName" type="java.lang.String">
            <column name="PRONAME" />
        </property>
        <!-- 多對多配置,相對於與兩表有聯系的新表進行配置 -->
        <set name="employees" table="proemp" cascade="save-update">
            <!-- 確定關聯的外鍵列 -->
            <key>
                <column name="rproid"></column>
            </key>
            <!-- 集合屬性所對應的持久化類,以及關聯的外鍵列 -->
            <many-to-many class="com.imooc.entity.Employee" column="rempid"></many-to-many>
        </set>
    </class>
</hibernate-mapping>

employee.hbm.xml映射文件配置

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2017-8-9 15:55:46 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping>
    <class name="com.imooc.entity.Employee" table="EMPLOYEE">
        <id name="empId" type="int">
            <column name="EMPID" />
            <generator class="assigned" />
        </id>
        <property name="empName" type="java.lang.String">
            <column name="EMPNAME" />
        </property>
         <!-- 多對多配置,相對於與兩表有聯系的新表進行配置 -->
        <set name="projects" table="proemp" inverse="true">
               <!-- 確定關聯的外鍵列 -->
            <key>
                <column name="rempid"></column>
            </key>
            <!-- 集合屬性所對應的持久化類,以及關聯的外鍵 -->
            <many-to-many class="com.imooc.entity.Project" column="rproid"></many-to-many>
        </set>
    </class>
</hibernate-mapping>

四、關系中的反轉與級聯說明

  反轉通過映射文件中對集合的inverse屬性的設置,來控制關聯關系。默認值為false,則關系兩方都可以控制,可能在更新時會造成重復更新的情況,降低系統性能,在多對多關系中,如果兩方都能控制並進行更新操作則可能報錯。以project和employee為例,如果兩方都添加另一方到set集合中,則中間表proemp會添加進兩條相同的記錄則會報錯。

  通常的做法是在一對多關系中,將一的一方的inverse設為true(因為多的一方有外鍵可以知道一方的情況),由多的一方維護關聯關系;在多對多關系中,在任意一方設置都可。

  級聯是當一方進行保存,更新或刪除操作時,其關聯對象也執行相同操作。映射文件中通過對cascade屬性設置控制是否對關聯對象采用級聯操作。

  在一對多關聯關系執行保存操作時,如果不進行級聯操作只保存Grade,則會報錯,因為持久態對象grade關聯了瞬時態對象Student,這種情況不允許保存,可設置grade映射文件的cascade="save-update",多對多關系也適用級聯保存。

  級聯刪除:在一對多關系中,如果刪除grade記錄則與之相關的student的gid屬性為null(未設置級聯刪除),使用級聯刪除可將與之相關的student都刪除。

    多對多關系的級聯刪除也叫雙向級聯刪除,刪除某個學生時,與之關聯的課程都要被刪除,而與被關聯課程相關的其他學生也需要刪除。

Hibernate的關聯關系映射