一對一關聯性映射即為關係雙方都含有對方一個引用,其實在生活中一對一關聯性也很常見,比如人和身份證,學生和學號等,都是一對一的關係映射,一對一映射分為單向的和雙向的,沒種關係映射又可以分為主鍵關聯映射,唯一外部索引鍵關聯映射。
一:主鍵關聯映射
一般一對一主鍵關聯映射通過foreign主鍵產生器使用另外一個相關聯的對象的標識符。通常和<one-to-one>聯合起來使用。一對一主鍵關聯映射原理:讓兩個實體的主鍵一樣,這樣就不需要加入多餘的欄位。此種關聯映射有一定的缺點:單向一對一主鍵關聯實際上限制很多,因為你只有IdCard插入了那才能有這個Person.我們看一下具體樣本:
根據上面的關係類圖,我們再來看一下實體類的定義
實體IdCard.java
public class IdCard{ private String id; private int number; private Person person;}
實體:Person.java
public class Person{ private String id; private String name; private IdCard idCard;}
IdCard的設定檔:
<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><hibernate-mapping> <classname="com.jzq.hibernate2.IdCard" table="t_IdCard"><!--這裡我們應該注意的是此處的主鍵建置原則,這裡的主鍵是利用的外鍵建置原則產生的,這裡的主鍵關聯著idcard表中的主鍵,也就是說,保證Person和idcard的主鍵相同。--> <id name="id"> <generator class="native"/> </id> <property name="cardNo"/> </class></hibernate-mapping>
person的設定檔:
<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><hibernate-mapping> <classname="com.jzq.hibernate2.IdCard" table="t_Person"> <!--id引用外部主鍵 --> <id name="id"> <generatorclass="foreign"> <paramname="property">idCard</param> </generator> </id> <property name="name"/> <one-to-one name="idCard"constrained="true"/> </class></hibernate-mapping>
註:one-to-one標籤告訴hibernate根據主鍵載入引用對象 , 把person中的主鍵拿到idCard表中進行尋找,然後把查到的資訊載入到引用對象中採用一對一主鍵約束,那麼必須設定constrained屬性,表示當前主鍵作為外鍵參照了該屬性在一對一主鍵關聯映射中預設問級聯屬性
配置完了以後我們來看一下具體的增刪改查操作:
Person person = newPerson(); person.setName("zhangsan"); IdCard idCard = new IdCard(); idCard.setNumber(987654); person.setIdCard(idCard); idCard.setPerson(person); Session session = sessionFactory.openSession(); Transaction tx = null; try { tx =session.beginTransaction(); session.save(person); tx.commit(); } catch(Exception ex) { ex.printStackTrace(); if(null != tx) { tx.rollback(); } } finally { session.close(); } //--------------------------------------------------- // Session session = sessionFactory.openSession();// Transaction tx = null;// Person person = null;// try// {// tx =session.beginTransaction();// person =(Person)session.get(Person.class,"402881ec2ebd7e77012ebd7e79e40001");// tx.commit();// }// catch(Exception ex)// {// if(null != tx)// {// tx.rollback();// }// }// finally// {// session.close();// }// System.out.println(person.getName());// System.out.println(person.getIdCard().getNumber()); //----------------------------------------- // Session session = sessionFactory.openSession();// Transaction tx = null;// // Person person = null;// try// {// tx =session.beginTransaction();// // person =(Person)session.get(Person.class,"402881ec2ebd7e77012ebd7e79e40001");// // person.setName("lisi"); // tx.commit();// }// catch(Exception ex)// {// if(null != tx)// {// tx.rollback();// }// }// finally// {// session.close();// }// System.out.println(person.getName()); //-----------------------------------------// Session session = sessionFactory.openSession();// Transaction tx = null;// Person person = null;// try// {// tx =session.beginTransaction(); // person =(Person)session.get(Person.class,"402881ec2ebd7e77012ebd7e79e40001"); // session.delete(person); // tx.commit();// }// catch(Exception ex)// {// if(null != tx)// {// tx.rollback();// }// }// finally// {// session.close();// }
通過執行查詢,我們可以發現,hibernate的一對一預設執行的檢索方式是外串連檢索方式,如果我們不想用外串連檢索方式,我們可以設定一下one-to-one的fetch屬性,他有兩個值,一個是select,一個是jion。我想大家通過字面也能猜出他們所對應的檢索方式。
Hibernate一對一中也可以設定消極式載入,一對一預設使用的是立即載入,如果需要使用消極式載入,那麼需要在one-to-one元素中將constrained屬性設為true,並且將待載入的一方的class元素中的lazy屬性設為true(或者不去設定,因為該屬性預設值就是true)。一對一載入時預設使用左外串連,可以通過修改fetch屬性為select修改成每次發送一條select語句的形式。
唯一外部索引鍵關聯映射:其實它是一對多的特殊情況,它基本和一對多是完全相同的,只不過需要配置一個屬性而已。其本質上是一對多的蛻化形式。在many-to-one元素中增加unique=”true”屬性就變成了一對一。
二、一對唯一外部索引鍵關聯映射——單向
1.一對唯一外部索引鍵關聯映射是多對一關聯映射的特例,可以採用<many-to-one>標籤,指定多的一端的unique=true,這樣就限 制了多的一端的多重性為一,通過這種手段映射一對一唯一外部索引鍵關聯
2.領域模型圖:
3.配置
Person.hbm.xml:
<class name="com.bjsxt.hibernate.Person"table="t_person"><id name="id"><generator class="native"/></id><property name="name"/><many-to-one name="idCard" unique="true"/></class>
IDCard.hbm.xml:
<class name="com.bjsxt.hibernate.IdCard"table="t_idcard"><id name="id"><generator class="native"/></id><property name="cardNo"/></class>
三、 一對唯一外部索引鍵關聯映射——雙向
1.一對一唯一外部索引鍵關聯雙向,需要在另一端(idcard),添加<one-to-one>標籤,指示hibernate如何載入其關聯對象,預設根據主鍵載入person,外部索引鍵關聯映射中,因為兩個實體採用的是person的外鍵維護的關係,所以不能指定主鍵載入person,而要根據person的外鍵載入,所以採用如下映射方式:
<one-to-one name="person"property-ref="idCard"/>
2.領域模型圖:
3.具體配置:
Person.hbm.xml:
<class name="com.bjsxt.hibernate.Person"table="t_person"><id name="id"><generator class="native"/></id><property name="name"/><many-to-one name="idCard" unique="true"/></class>
IDCard.hbm.xml
<class name="com.bjsxt.hibernate.IdCard"table="t_idcard"><id name="id"><generator class="native"/></id><property name="cardNo"/><one-to-one name="person"property-ref="idCard"/></class>