Hibernate關聯關係映射之一對一關聯關係,hibernate一對一
人和身份證之間就是一個典型的一對一關聯關係。實現一對一關聯關係映射的方式有兩種一種是基於外鍵,一種是基於主鍵,下面我們先看基於外鍵的關聯方式
首先看他們的實體類
Person類
package entity;public class Person {private Integer id;private String name;private IdCard idCard;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public IdCard getIdCard() {return idCard;}public void setIdCard(IdCard idCard) {this.idCard = idCard;}}
然後看IdCard類
package entity;public class IdCard {private Integer id;private String number;private Person person;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getNumber() {return number;}public void setNumber(String number) {this.number = number;}public Person getPerson() {return person;}public void setPerson(Person person) {this.person = person;}}
這裡在Person類和IdCard類中分別有一個對方類型的屬性。
然後看他們之間的關聯關係映射,首先看Person.hbm.xml
<?xml version="1.0" encoding="utf-8"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"><hibernate-mapping> <class name="entity.Person" table="Person" schema="MYHR"> <id name="id" type="int"> <column name="ID" /> <generator class="assigned" /> </id> <property name="name" type="string"> <column name="NAME" not-null="true" /> </property> <!-- idCard屬性,IdCard類型,表達本類與IdCard的一對一關聯 --> <!-- 採用基於外鍵的一對一,本方無外鍵方 --> <!-- property-ref屬性:對方映射中外鍵類對應的屬性名稱 --> <one-to-one name="idCard" class="entity.IdCard" property-ref="person"> </one-to-one> </class></hibernate-mapping>
然後看一下IdCard.hbm.xml文檔
<?xml version="1.0" encoding="utf-8"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"><hibernate-mapping> <class name="entity.IdCard" table="IdCard" schema="MYHR"> <id name="id"> <column name="ID"/> <generator class="assigned" /> </id> <property name="number"> <column name="NAME" not-null="true" /> </property> <!-- person屬性,Person類型,表示與Person類的一對一關聯關係 --> <!-- 採用基於外鍵的一對一關聯方式,本方有外鍵 --> <many-to-one name="person" column="personId" class="entity.Person" unique="true"></many-to-one> </class></hibernate-mapping>
這樣Person和IdCard之間的一對一關聯關係就搭建好了,然後看一下測試類別
package test;import static org.junit.Assert.*;import org.hibernate.Session;import org.hibernate.Transaction;import entity.IdCard;import entity.Person;import factory.HibernateSessionFactory;public class Test {private Session session = null;private Transaction tran = null;@org.junit.Testpublic void save() {session = HibernateSessionFactory.getSession();tran = session.beginTransaction();try{//建立對象Person p = new Person();p.setId(1);p.setName("張三");IdCard idCard = new IdCard();idCard.setId(1);idCard.setNumber("10001");p.setIdCard(idCard);idCard.setPerson(p);session.save(p);session.save(idCard);tran.commit();}catch(Exception e){tran.rollback();}}@org.junit.Testpublic void Get() {session = HibernateSessionFactory.getSession();tran = session.beginTransaction();try{Person person = (Person) session.get(Person.class, 1);IdCard idCard = person.getIdCard();System.out.println(person.getName()+"社會安全號碼:"+idCard.getNumber());tran.commit();}catch(Exception e){tran.rollback();}}//解除關係@org.junit.Testpublic void RemoveRelation() {session = HibernateSessionFactory.getSession();tran = session.beginTransaction();try{//從有外鍵方接觸關聯關係可以,不可以從無外鍵方解除IdCard idCard = (IdCard)session.get(IdCard.class, 1);idCard.setPerson(null);tran.commit();}catch(Exception e){tran.rollback();}}//刪除@org.junit.Testpublic void DeleteRelation() {session = HibernateSessionFactory.getSession();tran = session.beginTransaction();try{//如果沒有關聯對方,可以直接刪除。 //如果有關聯對方,且可以維護關聯關係,他就會先刪除關聯關係,在刪除自己。//如果有關聯關係,且不能維護關聯關係,所以會執行刪除自己,並且拋出異常。IdCard idCard = (IdCard)session.get(IdCard.class, 1);session.delete(idCard);tran.commit();}catch(Exception e){tran.rollback();}}}
這就是基於外鍵方式,基於主鍵的方式只需要在以上基礎修改一下對應檔即可,下面分別看一下修改後的對應檔
首先看Person.hbm.xml
<?xml version="1.0" encoding="utf-8"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"><hibernate-mapping package="entity"> <class name="entity.Person" table="Person" schema="MYHR"> <id name="id" type="int"> <column name="ID" /> <generator class="assigned" /> </id> <property name="name" type="string"> <column name="NAME" not-null="true" /> </property> <!-- idCard屬性,IdCard類型,表達本類與IdCard的一對一關聯 --> <!-- 採用基於主鍵的一對一,本方無外鍵方 --> <one-to-one name="idCard" class="entity.IdCard"/> </class></hibernate-mapping>
然後看IdCard.hbm.xml
<?xml version="1.0" encoding="utf-8"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"><hibernate-mapping package="entity"><class name="entity.IdCard" table="IdCard" schema="MYHR"><id name="id" type="int"><column name="ID" /><!-- 當使用基於主鍵的一對一映射時,有外鍵方的主鍵建置原則是foreign, --><!-- 參數property:產生主索引值時所根據的對象 --><generator class="foreign"> <param name="property">person</param></generator></id><property name="number" type="string"><column name="NAME" not-null="true" /></property><!-- person屬性,Person類型,表示與Person類的一對一關聯關係 --><!-- 採用基於主鍵的一對一關聯方式,本方有外鍵 --><one-to-one name="person" class="entity.Person"constrained="true" /></class></hibernate-mapping>
hibernate有幾種映射關係
Hibernate的關聯關係映射大概有這麼幾種:
1、單向N-1
2、單向1-1
3、單向1-N
4、單向N-N
5、雙向1-N
6、雙向N-N
7、雙向1-1
下面就對這七種關聯關係映射進行一個簡單的總結:
一、單向的多對一
看兩個POJO
public class Person{
private int pid;
private String name;
private Address address;
...//產生相應的getter、setter方法
}
----------------------------------------
public class Address{
private int id;
private String detail;
...//產生相應的getter、setter方法
}
這裡我們需要維護的關係是多個Person可以對應同一個地址,使用單向的N-1映射我們只需要在多的一端加入一個外鍵指向一的一端即可
**看設定檔
<class name="Person">
<id name="id">
<generator class="native"/>
</id>
...//部分欄位配置省略
<many-to-one name="address" column="addressId"/>//關鍵配置
</class>
這樣配置以後hibernate就會幫我們在多的一端(Person)添加一個外鍵addressId指向一的一端
二、單向的1-1(外部索引鍵關聯)
可以採用<many-to-one>標籤,指定多的一端的unique=true,這樣就限制了多的一端的多重性唯一
通過這種手段映射一對一唯一外部索引鍵關聯
設定檔只需要修改為:
<many-to-one name="address" column="addressId" unique="true"/>
三、單向的1-N
**看代碼,我們知道一個班級有多名學生,這就是一個典型的1-N關係
public class Classes {
private int id;
private String name;
private Set students;
...//產生相應的getter、setter方法
}
---------------------------------------------------------------------------
public class Student {
private int id;
private String name;
..//產生相應是getter、setter方法
}
**映射原理:一對多關聯映射,在多的一端添加一個外鍵指向一的一端,它維護的關係是一指向多
**設定檔:
<class name="Classes" table="t_classes">
<id......餘下全文>>
Hibernate關係映射問題
基本上都比較常用,非說那個不常用的話一對一用得可能能少點,下面說下我的理解,我盡量說通俗點
我下面就舉幾個例子你就明白了:
1、一對一,比如一個表的欄位有100多個,而且其中有40個其他表可能有用,那麼你把這個表拆分成兩個表,並且兩個表中的資料都是一條記錄對應一條記錄,某一個表中存放另一個對應表的id用來維護兩個記錄之間的關係,因為本來這兩條記錄原來就是一條記錄,不知道這麼說你能明白嗎?
2、一對多,如:部門表與使用者表,一個部門是不是有多個使用者,但是一個使用者有且只有一個部門,很清晰了吧
3、多對一,相當於吧部門表與使用者表打顛倒
4、多對多,其實就是一對多與多對一結合起來實現的關係,如使用者表與許可權表,一個使用者有多個許可權,而一個許可權同時對應多個使用者,兩個結合起來就是多對多
5、單向雙向只是hibernate的概念,比如你這兩個表A---表B,這樣通過表A來維護表B的資料,但是表B不能維護表A,這就是單項,雙向現在應該就好解釋了,通過兩個表都可以相互管理對方的資料。書面點,單項就是由父類管理關聯關係,子類無法管理,雙向父類子類都可管理。
hibernate提出的這些關係都有相應的配置,其實這些關係在資料庫中一直是存在的,只是hibernate對這些關係都通過不同的配置實現,單向和雙向也有相應的配置,這些功能當然也可以不通過hibernate配置實現,自己在代碼中維護這塊關係也可以,單雙向,資料庫中沒有類似相關概念,hibernate提出這塊功能,我們可以通過配置完成他們的限制功能。想想如果我們代碼只提供使用者表管理部門表的功能,不給通過部門系統管理使用者的方法,那麼這是不是就類似於hibernate的單向概念呢?
時間有限就說這麼多,都是自己在項目中的一些積累,可能有些地方理解不夠深刻,包含包含