1. 程式人生 > >Hibernate (八)一對一 (外來鍵關聯方式)

Hibernate (八)一對一 (外來鍵關聯方式)

一對一 對映有兩種方式:
主鍵關聯: id 對應 id 兩個主鍵必須相同
外來鍵關聯: id 對應 xxxid 專門設定一個外來鍵屬性 (推薦使用)

外來鍵關聯方式

例如:下面的例子IdCard 表會有一個專門的外來鍵屬性 personId 對應 person 主鍵id

IdCard.java

public class IdCard {
    private Integer id;
    private String number;
    private Person person; // 關聯的公民

IdCard.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"> <hibernate-mapping package="cn.itcast.i_hbm_oneToOne"> <class name="IdCard" table="idCard"> <id name="id"> <generator
class="native">
</generator> </id> <property name="number"/> <!-- person屬性,Person型別。 表達的是本類與Person的一對一。 採用基於外來鍵的一對一對映方式,本方有外來鍵方。 --> <many-to-one name="person" class="Person" column="personId" unique="true"></many-to-one
>
</class> </hibernate-mapping>

Person.java

public class Person {
    private Integer id;
    private String name;
    private IdCard idCard; // 關聯的身份證

Person.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">

<hibernate-mapping package="cn.itcast.i_hbm_oneToOne">
    <class name="Person" table="person">
        <id name="id">
            <generator class="native"></generator>
        </id>
        <property name="name"/>

        <!-- idCard屬性,IdCard型別。
            表達的是本類與IdCard的一對一。
            採用基於外來鍵的一對一對映方式,本方無外來鍵方。
            property-ref屬性:
                寫的是對方對映中外來鍵列對應的屬性名。  
         -->
        <one-to-one name="idCard" class="IdCard" property-ref="person"/>
    </class>
</hibernate-mapping>

第二種方式:

主鍵關聯

其他一樣只是,對映檔案不同
IdCard.hbm.xml

... ...
<hibernate-mapping package="cn.itcast.i_hbm_oneToOne2">

    <class name="IdCard" table="idCard2">
        <id name="id">
            <!-- 當使用基於主鍵的一對一對映時,
                有外來鍵方的主鍵生成策略一定要是foreign。
                引數property:
                    生成主鍵值時所根據的物件。
             -->
            <generator class="foreign">
                <param name="property">person</param>
            </generator>
        </id>
        <property name="number"/>

        <!-- person屬性,Person型別。
            表達的是本類與Person的一對一。
            採用基於主鍵的一對一對映方式,本方有外來鍵方。 -->
        <one-to-one name="person" class="Person" constrained="true"></one-to-one>
    </class>

</hibernate-mapping>

Person.hbm.xml

... ...
<hibernate-mapping package="cn.itcast.i_hbm_oneToOne2">
    <class name="Person" table="person2">
        <id name="id">
            <generator class="native"></generator>
        </id>
        <property name="name"/>

        <!-- idCard屬性,IdCard型別。
            表達的是本類與IdCard的一對一。
            採用基於主鍵的一對一對映方式,本方無外來鍵方。
         -->
        <one-to-one name="idCard" class="IdCard"></one-to-one>
    </class>
</hibernate-mapping>

測試程式碼

package cn.itcast.i_hbm_oneToOne;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.Test;

public class App {

    private static SessionFactory sessionFactory = new Configuration()//
            .configure()//
            .addClass(Person.class)// 新增Hibernate實體類(載入對應的對映檔案)
            .addClass(IdCard.class)// 新增Hibernate實體類(載入對應的對映檔案)
            .buildSessionFactory();

    // 儲存,有關聯關係
    @Test
    public void testSave() throws Exception {
        Session session = sessionFactory.openSession();
        session.beginTransaction();
        // --------------------------------------------

        // 新建物件
        Person person = new Person();
        person.setName("張三");

        IdCard idCard = new IdCard();
        idCard.setNumber("100000011X");

        // 關聯起來
        // person.setIdCard(idCard);
        idCard.setPerson(person);

        // 儲存
        session.save(person);
        session.save(idCard);

        // --------------------------------------------
        session.getTransaction().commit();
        session.close();
    }

    // 獲取,可以獲取到關聯的對方
    @Test
    public void testGet() throws Exception {
        Session session = sessionFactory.openSession();
        session.beginTransaction();
        // --------------------------------------------

        // 獲取一方,並顯示另一方資訊
        // Person person = (Person) session.get(Person.class, 1);
        // System.out.println(person);
        // System.out.println(person.getIdCard());

        IdCard idCard = (IdCard) session.get(IdCard.class, 1);
        System.out.println(idCard);
        System.out.println(idCard.getPerson());

        // --------------------------------------------
        session.getTransaction().commit();
        session.close();

    }

    // 解除關聯關係:一對一中,只能有外來鍵方可以維護關聯關係。
    @Test
    public void testRemoveRelation() throws Exception {
        Session session = sessionFactory.openSession();
        session.beginTransaction();
        // --------------------------------------------

        // 從有外來鍵方解除關係,可以。
        // IdCard idCard = (IdCard) session.get(IdCard.class, 1);
        // idCard.setPerson(null);

        // 從無外來鍵方解除關係,不可以。
        Person person = (Person) session.get(Person.class, 1);
        person.setIdCard(null);

        // --------------------------------------------
        session.getTransaction().commit();
        session.close();
    }

    // 刪除物件,對關聯物件的影響
    @Test
    public void testDelete() throws Exception {
        Session session = sessionFactory.openSession();
        session.beginTransaction();
        // --------------------------------------------

        // a, 如果沒有關聯的對方:能刪除。
        // b, 如果有關聯的對方且可以維護關聯關係(有外來鍵方),他就會先刪除關聯關係,再刪除自己。
        // c, 如果有關聯的對方且不能維護關聯關係(無外來鍵方),所以會直接執行刪除自己,就會有異常。

        IdCard idCard = (IdCard) session.get(IdCard.class, 1);
        session.delete(idCard);

        // Person person = (Person) session.get(Person.class, 1);
        // session.delete(person);

        // --------------------------------------------
        session.getTransaction().commit();
        session.close();
    }

}