首先我們瞭解一個名詞ORM,全稱是(ObjectRelational Mapping),即對象關係映射。ORM的實現思想就是將關係數據庫中表的數據映射成對象,以對象的形式展現,這樣開發人員就可以把對數據庫的操作轉化爲對這些對象的操作。Hibernate正是實現了這種思想,達到了方便開發人員以面向對象的思想來實現對數據庫的操作。
Hibernate在實現ORM功能的時候主要用到的文件有:映射類(*.java)、映射文件(*.hbm.xml)和數據庫配置文件(*.properties/*.cfg.xml),它們各自的作用如下。
映射類(*.java):它是描述數據庫表的結構,表中的字段在類中被描述成屬性,將來就可以實現把表中的記錄映射成爲該類的對象了。
映射文件(*.hbm.xml):它是指定數據庫表和映射類之間的關係,包括映射類和數據庫表的對應關係、表字段和類屬性類型的對應關係以及表字段和類屬性名稱的對應關係等。
數據庫配置文件(*.properties/*.cfg.xml):它是指定與數據庫連接時需要的連接信息,比如連接哪種數據庫、登錄數據庫的用戶名、登錄密碼以及連接字符串等。當然還可以把映射類的地址映射信息放在這裏。
這裏我來說一下hibernate的映射關係:
這裏先對單向關聯和雙向關聯做一個簡單的解釋,下面的問題就更好理解了。
單向關聯:只需要單向的訪問關聯端。如規定老師可以訪問學生,而學生不能訪問老師。
雙向關聯:關聯的兩端可以相互訪問。如老師和學生可以互相訪問。
1、1與N的關係
(1)單向N-1關聯:
1)定義:只需要N的一端訪問1的一端。
2)如:用戶和組,用戶爲N端,組爲1端。多個用戶在一個組中,只需要從用戶這端找到他在哪個組,而哪個考慮這個組中有哪些用戶。
3)圖:
4)注:需要在N端加上1端的主鍵做爲N端的外鍵,來指向1的一端
5)在N端的group.hbm.xml的文件中採用如下標籤映射:
<many-to-onename="group" column="groupid"></many-to-one>
在hibernate.cfg.xml中要配置
<mappingresource="com/lsh/hibernate/**.hbm.xml"/>
也就是將hibernate與數據庫的對象關係映射文件**.hbm.xml載入內存
(2)單向1-N關聯:
1)定義:只需要1的一端訪問N的一端
2)如:班級和學生,班級爲1端,學生爲N端,一個班級有多個學生,只需要從班級這端找到所有學生,而不需要學生去找到班級
3)圖:
4)注:同N-1端一樣,需要在N端加上1端的主鍵做爲N端的外鍵,來指向1的一端
5)在1端的classes.hbm.xml的文件中採用如下的映射標籤
<setname="students" >
<key column="classesid"/>
<one-to-many class="com.lsh.hibernate.Student"/>
</set>
(3)雙向1-N關聯
1)定義:兩端可以互相訪問
2)如:如班級和學生,班級爲1端,學生爲N端,一個班級有多個學生,即可以從班級這端查找學生,也可以從學生這端找到班級。
3)圖:
4)注:雙向關聯的時候,讓其每一端都映射到classesid上。在1端維護關係存在缺陷,所以將單向的1-N關聯都設置成雙向的,將這個關係字段交給N端維護,不讓1端維護,這樣就可以保證只對其查找,不會對其更新。
5)在1端的classes.hbm.xml的文件中採用如下的映射標籤
<set name="students"inverse="true">
<key column="classesid"/>
<one-to-many class="com.lsh.hibernate.Student"/>
</set>
6)在N端的student.hbm.xml的文件中採用如下的映射標籤
<many-to-one name="classes"column="classesid"></many-to-one>
2、1與1的關係
(1)單向1對1主鍵關聯
1)定義:其中某個1的一端訪問另一個1的一端
2)如:人和身份證, 1個人只有一張身份證,即可以根據這個人找到身份證,而不需要根據身份證去找這個人
3)圖:
4)注:讓兩個對象具有相同的主鍵,以表明他們之間的一一對應關係;數據庫表不會有額外的字段來維護他們之間的關係,僅通過表的主鍵來關聯。
5)在1端的person.hbm.xml的文件中採用如下的映射標籤
<class name="com.lsh.hibernate.Person" table="t_person">
<id name="id">
<!--採用foreign生成策略,foreign會取得關聯對象的標識 -->
<generator class="foreign">
<!-- property直關聯對象 -->
<param name="property">idCard</param>
</generator>
</id>
<property name="name"></property>
<!--
one-to-one 指示hibernate如何加載其關聯對象,默認根據主鍵加載
也就是拿到關係字段值,根究對端的主鍵來加載關聯對象
constrained="true"表示,當前主鍵(person主鍵)還是一個外鍵
參照了對端的主鍵(IdCard的主鍵),也就是會生成外鍵約束語句
-->
<one-to-one name="idCard" constrained="true"></one-to-one>
</class>
6)在1端的idCard.hbm.xml的文件中採用如下的映射標籤
<class name="com.lsh.hibernate.IdCard" table="t_idCard">
<id name="id">
<generator class="native"/>
</id>
<property name="cardNo"/>
</class>
(2)單向1對1唯一外鍵關聯
1)定義:其中某個1的一端訪問另一個1的一端
2)如:人和卡,一個人有一張卡,即可以通過這個人去找到卡
3)圖:
4)注:一對一唯一外鍵關聯映射是多對一的特例,採用<many-to-one>標籤來映射,指定多的一端unique爲true,就是這樣來映射的
5)在1端的person.hbm.xml的文件中採用如下的映射標籤
<class name="com.lsh.hibernate.Person" table="t_person">
<id name="id">
<generator class="native"></generator>
</id>
<property name="name"></property>
<many-to-one name="idCard" unique="true"></many-to-one>
</class>
(3)雙向1對1主鍵關聯
1)定義:兩端可以互相訪問
2)如:人和身份證, 1個人有一張身份證,即可以根據這個人找到身份證,也可根據身份證去找這個人
3)圖:
4)注: 需要在IdCard加入<one-to-one>標籤,指示hibernate將關聯對象Person根據主鍵加載上來,<one-to-one>不影響存儲,隻影響加載
5)在1端的person.hbm.xml的文件中採用如下的映射標籤
<class name="com.lsh.hibernate.Person" table="t_person">
<id name="id">
<!--採用foreign生成策略,foreign會取得關聯對象的標識 -->
<generator class="foreign">
<!-- property直關聯對象 -->
<param name="property">idCard</param>
</generator>
</id>
<property name="name"></property>
<!--
one-to-one 指示hibernate如何加載其關聯對象,默認根據主鍵加載也就是拿到關係字段值,根究對端的主鍵來加載關聯對象
constrained="true"表示,當前主鍵(person主鍵)還是一個外鍵 參照了對端的主鍵(IdCard的主鍵),也就是會生成外鍵約束語句
-->
<one-to-one name="idCard" constrained="true"></one-to-one>
</class>
6)在1端的idCard.hbm.xml的文件中採用如下的映射標籤
<class name="com.lsh.hibernate.IdCard" table="t_idCard">
<id name="id">
<generator class="native"/>
</id>
<property name="cardNo"/>
<one-to-one name="person" fetch="join"/>
</class>
(4)雙向1對1唯一外鍵關聯
1)定義:兩端可以互相訪問
2)如:人和卡,一個人有一張卡,即可以通過這個人去找到卡 ,也可以通過這張卡去找人
3)圖:
4)注:一對一唯一外鍵關聯雙向採用<one-to-one>標籤來映射,必須指定<one-to-one> 標籤中property-ref屬性爲關係字段的名稱
5)在1端的person.hbm.xml的文件中採用如下的映射標籤
<class name="com.lsh.hibernate.Person" table="t_person">
<id name="id">
<generator class="native"></generator>
</id>
<property name="name"></property>
<many-to-one name="idCard" unique="true"></many-to-one>
</class>
6)在1端的idCard.hbm.xml的文件中採用如下的映射標籤
<class name="com.lsh.hibernate.IdCard" table="t_idCard">
<id name="id">
<generator class="native"/>
</id>
<property name="cardNo" />
<one-to-one name="person" property-ref="idCard"></one-to-one>
</class>
3、N與N的關係
(1)單向N對N關聯
1)定義:其中某個N的一端訪問另一個N的一端
2)如:用戶和角色,每個用戶有多個角色,每個角色有多個用戶,這裏表示的是用戶可以去查找角色,而不能角色查找用戶
3)圖:
4)注:多對多關聯映射,需要一箇中間表,hibernate會自動生成中間表,跟一對多一樣,也是用集合來表示
5)在N端的user.hbm.xml的文件中採用如下的映射標籤
<class name="com.lsh.hibernate.User" table="t_user">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<set name="roles" table="t_user_role">
<key column="user_id"/>
<many-to-many class="com.lsh.hibernate.Role" column="role_id"></many-to-many>
</set>
</class>
6)在1端的role.hbm.xml的文件中採用如下的映射標籤
<class name="com.lsh.hibernate.Role" table="t_role">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
</class>
(2)雙向N對N關聯
1)定義:兩端可以互相訪問
2)如:用戶和角色,每個用戶有多個角色,每個角色有多個用戶,用戶可以查找角色,角色也可以查找用戶
3)圖:
4)在N端的user.hbm.xml的文件中採用如下的映射標籤
<class name="com.lsh.hibernate.User" table="t_user">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<set name="roles" table="t_user_role">
<key column="user_id"/>
<many-to-many class="com.lsh.hibernate.Role" column="role_id"></many-to-many>
</set>
</class>
5)在1端的role.hbm.xml的文件中採用如下的映射標籤
<class name="com.lsh.hibernate.Role" table="t_role">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<set name="usersSet" table="t_user_role">
<key column="role_id"/>
<many-to-many class="com.lsh.hibernate.User" column="user_id"></many-to-many>
</set>
</class>
這裏只對簡單主鍵做了總結,下面還會對複合主鍵和繼承映射做相應的總結!