1. 程式人生 > >Hibernate學習之級聯操作3——一對一關聯關係

Hibernate學習之級聯操作3——一對一關聯關係

前面兩篇博文裡記錄了Hibernate級聯操作的一對多關聯關係和一對多雙向自身關聯關係,這一篇記錄的是一對一關聯關係,例如一個人對應一張身份證,一對一的關係又可以分為共用主鍵的方式和一對多的特殊情況(使用外來鍵關聯)這兩種,下面分別記錄這兩種方式,

一、共用主鍵的一對一關係

這裡舉例人和身份證的一對一關係,共用主鍵即certificate表中的id值,用的是person表中的id,下面是兩張表的結構:


person表中有兩個欄位:id和name,certificate表中也是兩個欄位:id和cetificate_number,這兩個表通過共用id關聯起來,即通過person表中的id,可以查到certificate表中對應id的cetificate_number,下面是兩個實體類,Person.java和Certificate.java:

package com.test.model;

public class Person {

	private String id;
	private String name;
	private Certificate idCard;

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Certificate getIdCard() {
		return idCard;
	}

	public void setIdCard(Certificate idCard) {
		this.idCard = idCard;
	}

}
package com.test.model;

public class Certificate {

	private String id;
	private String number;
	private Person person;
	
	public String getNumber() {
		return number;
	}

	public void setNumber(String number) {
		this.number = number;
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public Person getPerson() {
		return person;
	}

	public void setPerson(Person person) {
		this.person = person;
	}

}
由於person和certificate是一對一的關係,一個人對應一個身份證,一個身份證也只對應一個人,所以在Person類中包含了一個Certificate型別的成員變數,在Certificate類中包含了一個Person類的成員變數,下面是兩個類的hbm檔案:

Person.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">
<!-- 
    Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
    <class name="com.test.model.Person" table="person">
        <id name="id" unsaved-value="null" column="id">
            <generator class="uuid">
            </generator>
        </id>
        
        <property name="name" type="string">
        	<column name="name" length="20"></column>
        </property>
        
        <one-to-one name="idCard" fetch="join" class="com.test.model.Cetificate" cascade="all" ></one-to-one>
    </class>
</hibernate-mapping>

上面的Person.hbm.xml檔案中需要注意的有:id指定了uuid型別,則插入資料時會自動為id欄位生成uuid,one-to-one標籤指定了一對一的類為Cetificate類且cascade屬性為all,即對於person表的增刪改查都會級聯到certificate表

Certificate.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">
<!-- 
    Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
    <class name="com.test.model.Cetificate" table="cetificate">
    
        <id name="id" type="string" column="id">
            <generator class="foreign" >
            	<param name="property">person</param>
            </generator>
        </id>
        
        <property name="number" column="cetificate_number" type="string"></property>
        
        <one-to-one name="person" class="com.test.model.Person" cascade="none" constrained="true" fetch="join"></one-to-one>
    </class>
</hibernate-mapping>
上面的配置檔案中需要注意的是,cetificate表的id配置了foreign屬性,且裡面的param標籤中配了person,這裡的意思是,cetificate表的id來自於person表的id

下面是測試程式碼:

package com.test;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;

import com.test.model.Certificate;
import com.test.model.Person;

public class TestMain {

	public static void main(String[] args) {
		Person person = new Person();
		person.setName("zhangsan");
		Certificate card = new Certificate();
		card.setNumber("2134987123498298");
		card.setPerson(person);
		person.setIdCard(card);
		Session session = HibernateSessionFactory.getSession();
		Transaction trans = session.beginTransaction();
		try {
			session.save(person);
			trans.commit();
		} catch (HibernateException e) {
			e.printStackTrace();
			trans.rollback();
		} finally {
			HibernateSessionFactory.closeSession();
		}
	}

}
上面的程式碼執行後,在資料庫中查詢的資訊如下:



可以看到,在儲存person物件的時候,hibernate自動為person表生成了uuid型別的id,並且將該id用在了certificate表,所以上面的兩個表中對應的兩條資料的id是一樣的,這就是一對一關聯關係中的一種:共用主鍵

二、使用外來鍵關聯的一對一關係,這種一對一的關係是一對多關係的一種特殊情況,從下面的配置檔案中就可以看出來,這裡就不放java bean的程式碼了,還是有兩個實體類:Person和Certificate,他們含有如下圖所示的成員變數:

         

下面是Person.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">
<!-- 
    Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
    <class name="com.test.model.Person" table="person">
        <id name="id" unsaved-value="null" column="id">
            <generator class="uuid">
            </generator>
        </id>
        
        <property name="name" type="string">
        	<column name="name" length="20"></column>
        </property>
        
        <one-to-one name="cer" fetch="join" class="com.test.model.Certificate" cascade="all" ></one-to-one>
    </class>
</hibernate-mapping>
這裡的Person.hbm.xml與公用主鍵的方式中Person.hbm.xml沒有區別,區別在於Certificate.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">
<!-- 
    Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
    <class name="com.test.model.Certificate" table="certificate">
        <id name="id" column="id">
            <generator class="uuid">
            </generator>
        </id>
        
        <property name="number" type="string">
        	<column name="number" length="20"></column>
        </property>
        
        <many-to-one name="person" class="com.test.model.Person" unique="true" cascade="none" column="person_id"></many-to-one>
    </class>
</hibernate-mapping>
在Certificate.hbm.xml檔案中,指定了many-to-one標籤,看似多對一的關係,實際上有了unique="true"的條件後,就變成了一對一的關係了,即一張身份證只能對應一個人,執行下面的測試程式碼後:
package com.test;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;

import com.test.model.Certificate;
import com.test.model.Person;

public class Test {

	public static void main(String[] args) {
		Person person = new Person();
		person.setName("lisi");
		
		Certificate cer = new Certificate();
		cer.setNumber("9817234987");
		cer.setPerson(person);
		person.setCer(cer);
		
		Session session = HibernateSessionFactory.getSession();
		Transaction trans = session.beginTransaction();
		try {
			session.save(person);
			trans.commit();
		} catch (HibernateException e) {
			e.printStackTrace();
			trans.rollback();
		} finally {
			HibernateSessionFactory.closeSession();
		}
		
	}

}
在資料庫中檢視資訊如下圖所示:


可以看到,這兩張表通過外來鍵的形式關聯起來了,certificate表中的person_id參照了person表的id,這種形式的一對一關聯關係,是一對多的關聯關係的特例,即一對多的“多”的那一方,只有唯一的一個與“一”的那一方相對,下一篇將記錄多對多的關聯關係。