天天看點

《Hibernate學習筆記六》一對一關聯關系詳解《Hibernate學習筆記六》一對一關聯關系詳解

《Hibernate學習筆記六》一對一關聯關系詳解

從今天開始,就要開始學習關聯關系了,其中關聯關系,分為如下幾種:

1、一對一關聯關系

2、一對多關聯關系

3、多對一關聯 關系

4、多對多關聯關系

總的來說,雖然有如上幾種關聯方式,但是我們可以了解它隻是1中關聯方式,就 多對多關聯,這是因為其他的關聯方式都可以了解為此關聯方式的一種特殊方式。

其中,上面提到的關聯關系,都存在單向和雙向的關聯關系。

這篇博文主要介紹下一對一關聯關系。

一對一外鍵關聯關系包括:

1、一對一單向外鍵關聯關系的Annotation實作

2、一對一單向外鍵關聯關系的xml實作

3、一對一雙向外鍵關聯關系的Annotation實作

4、一對一雙向外鍵關聯關系的xml實作

與外鍵相對應的還有主鍵關聯。

一對一關聯

我們生活中有很多一對一關聯的例子,例如:”一夫一妻制”就是一對一的關聯關系。一個學生有一個身份證也是一個一對一的關聯關系。

一對一單向外鍵關聯關系Annotation實作

一對一關聯使用注解@OneToOne來進行修飾。

下面就以:”一夫一妻制”這個例子來進行分析。

Wife實體類

@Entity
    public class Wife {
    private int id;
    private String name;
    @Id
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }   
    }
           

Husband實體類

Huaband實體類中有一個Wife類的引用wife,并在getWife方法上添加了注解@OneToOne,如果我們想指定外鍵的名字,則通過注解@JoinColumn(name=”wifeId”)來指定,其中wifeId就是我們這個例子中指定的名字。

Husband實體類的具體代碼如下:

@Entity
    public class Husband {
    private int id;
    private String name;
    private Wife wife;
    @Id
    @GeneratedValue
    public int getId() {
        return id;
    }
    @OneToOne
    @JoinColumn(name="wifeId") //指定外鍵的名字為wifeId
    public Wife getWife() {
        return wife;
    }
    public void setWife(Wife wife) {
        this.wife = wife;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }


    }
           

hibernate.cfg.xml檔案内容不再貼出,與前幾篇博文的内容類似。

測試代碼如下:

public class TeacherTest {
    @Test
    public void testSchema(){
        ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().configure().build();
        Metadata metadata = new MetadataSources(serviceRegistry).buildMetadata();
        SchemaExport schemaExport = new SchemaExport();
        schemaExport.create(EnumSet.of(TargetType.DATABASE), metadata);
    }

    }
           

SchemaExport類主要用于将SQL語句輸出到資料庫中。

在控制台我們會看到如下的主要輸出資訊,其中包括兩條建表語句,一條插入外鍵的語句。

《Hibernate學習筆記六》一對一關聯關系詳解《Hibernate學習筆記六》一對一關聯關系詳解

以上,這樣我們就通過Annotation建立了Husband和Wife一對一單向外鍵關聯關系。

一對一單向外鍵關聯關系XXX.hbm.xml的實作

現在換一個例子,以一個學生有一個身份證這樣一個一對一的關聯關系來舉例分析。

Student類

package com.hibernate.model;

    public class Student {
    private int id;
    private String name;
    // id 、num、 student的getter和setter方法省略
    }
           

IdCard類

public class IdCard {
    private int id;
    private String num;
    private Student student;

    // id 、num、 student的getter和setter方法省略
    }
           

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="com.hibernate.model">
    <class name="IdCard" table="idcard" >
        <id name="id" column="id">
            <generator class="native"/>
        </id>
        <property name="num" column="num"/>
        <!--  一對一的關聯在xml檔案中用many-to-one   和unique="true"聯合來進行限制  -->
        <many-to-one name="student" column="studentId" unique="true"></many-to-one>      
    </class>
    </hibernate-mapping>
           

上面的代碼中:一對一的關聯關系在如下的代碼中指定:

<many-to-one name="student" column="studentId" unique="true"></many-to-one>
           

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">
    <hibernate-mapping package="com.hibernate.model">
    <class name="Student" table="student" >
        <id name="id" column="id">
            <generator class="native"/>
        </id>
        <property name="name" column="name"/>     
    </class>
    </hibernate-mapping>
           

這樣我們就将Student和IdCard通過外鍵建立了一對一的關聯。

測試檔案與第一個例子的測試檔案一樣,這裡不再貼出。

一對一雙向外鍵關聯Annotation實作

Student類

類中有一個Wife的引用wife。

@Entity
    public class Husband {
    private int id;
    private String name;
    private Wife wife;
    @Id
    @GeneratedValue
    public int getId() {
        return id;
    }
    @OneToOne
    @JoinColumn(name="wifeId") //指定外鍵的名字為wifeId
    public Wife getWife() {
        return wife;
    }
    //name屬性的get方法和所有屬性的set方法均省略。

    }
           

Wife實體類

@Entity
    public class Wife {
    private int id;
    private String name;
    private Husband husband;
    @OneToOne(mappedBy="wife") //這裡的意思為:外鍵的關聯是在Husband的wife對象上面來做,即Husband是主導
    public Husband getHusband() {
        return husband;
    }
    public void setHusband(Husband husband) {
        this.husband = husband;
    }
    @Id
    public int getId() {
        return id;
    }
    //name屬性的get方法和所有屬性的set方法均省略。
    }
           

Wife類中也有一個Husband類的引用,并且需要在getHusband()方法前用@OneToOne(mappedBy=”wife”)進行注解。如果隻用@OneToOne而不使用參數的注解,則會為表Husband和Wife都會建立一個外鍵的關聯,有備援。

最好的方法:凡是雙向關聯中,必須要設定@OneToOne(mappedBy=”XXX”)。

一對一雙向外鍵關聯XXX.hbm.xml檔案實作

即Student類和IdCard類中均有對方的一個引用,且在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="com.hibernate.model">
    <class name="IdCard" table="idcard" >
        <id name="id" column="id">
            <generator class="native"/>
        </id>
        <property name="num" column="num"/>
        <!--  一對一的關聯在xml檔案中用many-to-one   和unique="true"聯合來進行限制  -->
        <many-to-one name="student" column="studentId" unique="true"></many-to-one>

    </class>
    </hibernate-mapping>
           

而在Student.hbm.xml檔案中的内容,有一點變化,

加上了

<one-to-one name="idCard" class="IdCard" property-ref="student"/> 
           

完整内容如下:

<?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="com.hibernate.model">
    <class name="Student" table="student" >
        <id name="id" column="id">
            <generator class="native"/>
        </id>
        <property name="name" column="name"/>  
        <!--property-ref的參數是本類所關聯的類IdCard類中的Student的引用   -->
        <one-to-one name="idCard" class="IdCard" property-ref="student"/>    
    </class>
    </hibernate-mapping>
           

注意:在資料庫中,單向和雙向是沒有差別的,但是,在實體類中的對應關系是有差別的。

一對一主鍵關聯

在外鍵關聯中,例如,會在Husband表中生成一個wifeId的字段作為外鍵,而主鍵關聯則不會生成其它任意的字段。

一對一單向主鍵關聯Annotation實作

用如下的注解來實作:

@PrimaryKeyJoinColumn //用此注解表示主鍵關聯

@Entity
    public class Husband {
    private int id;
    private String name;
    private Wife wife;
    @Id
    @GeneratedValue
    public int getId() {
        return id;
    }
    @OneToOne
    //@JoinColumn(name="wifeId") //指定外鍵的名字為wifeId
    @PrimaryKeyJoinColumn  //用此注解表示主鍵關聯
    public Wife getWife() {
        return wife;
    }
    public void setWife(Wife wife) {
        this.wife = wife;
    }

    //一些屬性的getter/setter方法  省略
    }
           

一對一單向主鍵關聯xml檔案實作

在文檔中,給出的方法截圖如下:

《Hibernate學習筆記六》一對一關聯關系詳解《Hibernate學習筆記六》一對一關聯關系詳解

将上述方法應用到我們的Student類和IdCard類中,如下:

Student類

public class Student {
    private int id;
    private String name;    
    //...get、set方法

    }
           

IdCard類

public class IdCard {
    private int id;
    private String num;
    private Student student;
    //...get、set方法
    }
           

IdCard.hbm.xml檔案内容如下:

注意:此時的id生成政策。

<?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="com.hibernate.model">
    <class name="IdCard" table="idcard" >
        <id name="id" column="id">
            <generator class="foreign">
                <param name="property">student</param>
            </generator>
        </id>
        <property name="num" column="num"/>
        <!--    -->
        <one-to-one name="student" class="Student" constrained="true"></one-to-one>                 
    </class>
    </hibernate-mapping>
           

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">
    <hibernate-mapping package="com.hibernate.model">
    <class name="Student" table="student" >
        <id name="id" column="id">
            <generator class="native"/>
        </id>
        <property name="name" column="name"/>       
    </class>
    </hibernate-mapping>
           

測試結果如下:

《Hibernate學習筆記六》一對一關聯關系詳解《Hibernate學習筆記六》一對一關聯關系詳解

關于主鍵關聯這裡就不再進行過多的介紹,這是由于在實際項目中,一對一關聯關系并不太多,即使出現,我們一般也是采用一對一的外鍵進行關聯。

小結

由于使用Annotation比使用xml進行關聯關系更容易了解和實作。是以,建議使用。

繼續閱讀