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; } }
由於person和certificate是一對一的關係,一個人對應一個身份證,一個身份證也只對應一個人,所以在Person類中包含了一個Certificate型別的成員變數,在Certificate類中包含了一個Person類的成員變數,下面是兩個類的hbm檔案: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.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,這種形式的一對一關聯關係,是一對多的關聯關係的特例,即一對多的“多”的那一方,只有唯一的一個與“一”的那一方相對,下一篇將記錄多對多的關聯關係。