詞匯解釋
關系:事物之間相互作用、相互聯系的狀態。范圍最大。
聯系:在關系數據庫中表示實體與實體之間的聯系,1:1,1:n,m:n。
關聯:表示對象之間的關系,既有數量性,又有方向性;動詞:將對象之間通過某種方式聯系起來。
映射:這里指java對象和數據庫表的一種對應關系。動詞:形成這種對應關系。
級聯:有關系的雙方中操作一方,另一方也將采取一些動作。
關聯的聯系種類
在不考慮關聯的方向前提下,聯系就是關系數據庫中表示實體與實體之間的聯系,1:1,1:n,m:n。
一對一聯系(1:1):如用戶和身份證、一夫一妻
一對多聯系(1:n):如班級和學生
多對多聯系(m:n):如學生和選課
關聯的方向
關聯關系的方向可分為單向關聯和雙向關聯。
雙向關聯的方向其實就不重要了,因為通過任一一方都可以維護彼此的關系。也就是說:在雙向關聯中一對多和多對一都是一樣的。
單向關聯
在關聯標記例如<many-to-one>或者<one-to-many>,方向都是從左到右,換句話說是由左邊維護它們的關系,參見下面例子。
假設存在兩張表person表和address表,它們之間的聯系是n:1;
即一個人的居住地址是唯一的,一個地址卻可以多個人居住。
如果在應用的業務邏輯中,僅需要每個person實例能夠查詢得到其對應的Address實例,而Address實例並不需要查詢得到其對應的person實例。
<class name="Person" table="person"> <id name="id" > <generator class="native"/> </id> <many-to-one name="address" column="addressId" not-null="true"/> </class> <class name="Address" > <id name="id" column="addressId"> <generator class="native"/> </id> </class>
說明:
這是一個多對一的單向關聯:由多的一方來維護它們的關系,需要在name="Person"的class元素內加入關聯標記,<many-to-one>。這種關聯非常多。
假設存在兩張表person表和tel表,它們之間的聯系是1:n;
即一個人的聯系電話可能有多個,一個電話只能對應一個人。
如果在應用的業務邏輯中,我們僅僅關心每個person實例能夠查詢到其對應的所有tel實例,而tel實例並不需要查詢得到其對應的person實例。
<class name="Person"> <id name="id" column="personId"> <generator class="native"/> </id> <set name="tels"> <key column="personId" not-null="true" /> <one-to-many class="Tel"/> </set> </class> <class name="Tel"> <id name="id" column="telId"> <generator class="native"/> </id> </class>
說明:
這是一個一對多的單向關聯:由一的一方來維護他們的關系,需要在name="Person"的class元素內加入關聯標記,<one-to-many>。這種關聯相對要少一些。大部分情況下我們都是操作多的一方的實例。
雙向關聯
在兩邊同時配置單向關聯,就構成了雙向管理。實際開發過程中,很多時候都是需要雙向關聯的,它在解決單向一對多維護關系的過程中存在的缺陷起了一定的修補作用。
假設存在兩張表person表和address表,它們之間的聯系是n:1;
即一個人的居住地址是唯一的,一個地址卻可以多個人居住。
既需要每個person實例能夠查詢得到其對應的Address實例,Address實例也需要查詢得到其對應的person實例。
<class name="Person"> <id name="id" column="personId"> <generator class="native"/> </id> <many-to-one name="address" column="addressId" not-null="true"/> </class> <class name="Address"> <id name="id" column="addressId"> <generator class="native"/> </id> <set name="people" inverse="true"> <key column="addressId"/> <one-to-many class="Person"/> </set> </class>
說明:
這是一個多對一雙向關聯。由雙方維護彼此的關系。需要在name="Person"的class元素內加入關聯標記,<many-to-one>。同時在name="Address"的class元素內加入集合映射<set>,並在其中加入關聯標記:<one-to-many>。
關聯標記
在hbm.xml中,關聯標記<one-to-one>、<many-to-one>、<one-to-many>、<many-to-many>,關聯的方向都是是從左到右。
關聯標記屬性
簡單介紹下面幾個,除了name是必須,其余都是可選的。更多的我們參考官文檔。
name="對應本類的屬性名"
column="映射到本表的字段名"
class="映射到本表的實體類"
unique="ture|false":(數據庫外鍵字段生成一個唯一約束)
not-null="ture|false"默認false(數據庫外鍵字段是否允許為空值)
lazy="ture|false"默認proxy(延遲加載)
關於cascade(級聯)屬性
級聯的意思是指定兩個對象之間的操作聯動關系,對一個對象執行了操作之后,對其指定的級聯對象也需要執行相同的操作
總共可以取值為:all、none、save-update、delete
all-代表在所有的情況下都執行級聯操作
none-在所有情況下都不執行級聯操作
save-update-在保存和更新的時候執行級聯操作
delete-在刪除的時候執行級聯操作
集合映射標記<set>
<set name="peoples" inverse="true"> <key column="addressId"/> <one-to-many class="Person"/> </set>
<set name="peoples" inverse="true">name為持久化對象的集合的屬性名稱。
<key column="classid" > column外鍵的名稱
<one-to-many class=“cn.edu.bzu.hibernate.Student" /> class持久化類
關於inverse屬性
控制反轉,主要用在一對多,多對對雙向關聯上,inverse可以設置到<set>集合上, 默認inverse為false。為true表示反轉,由對方負責;反之,不反轉,自己負責;如果不設,one和many兩方都要負責控制,因此,會引發重復的sql語句以及重復添加數據。
誰是多誰是一
我們說一對一,多對一,多對多是誰對誰呢?在映射文件(.hbm.xml)中class元素中的對象關聯標記中,比如<many-to-one>
那么class元素的屬性name就是many,<many-to-one>標記中 name就是one。同時column="addressId"指明了person表的外鍵。
<class name="Person" table="person"> <id name="id" > <generator class="native"/> </id> <many-to-one name="address" column="addressId" not-null="true"/> </class>
上面例子中Person就是many,address就是one。
可以這么理解<many-to-one>在誰里面,誰就是many,<many-to-one>的屬性name就是one。
單向關聯hbm.xml配置
單向關聯常用的是多對一
單向 many-to-one 關聯是最常見的單向關聯關系。這種關聯是數據庫關系模式中的多對一:
這個表的一個外鍵引用目標表的主鍵字段。
下面例子中的person與address聯系(數據庫用語)為n:1,可以這么理解:
即一個人的居住地址是唯一的,一個地址卻可以多個人居住。
<class name="Person" table="person"> <id name="id" > <generator class="native"/> </id> <many-to-one name="address" column="addressId" not-null="true"/> </class> <class name="Address" > <id name="id" column="addressId"> <generator class="native"/> </id> </class>
注意:<many-to-one>標簽中column="addressId",為person表添加一個外鍵addressId。
sql輸出:
create table Person ( personId bigint not null primary key, addressId bigint not null ) create table Address ( addressId bigint not null primary key )
雙向關聯hbm.xml配置
1.一對多/多對一
雙向多對一關聯 是最常見的關聯關系。下面的例子解釋了這種標准的父/子關聯關系。
下面例子中的person與address聯系(數據庫用語)為n:1,可以這么理解:
即一個人的居住地址是唯一的,一個地址卻可以多個人居住。
<class name="Person"> <id name="id" column="personId"> <generator class="native"/> </id> <many-to-one name="address" column="addressId" not-null="true"/> </class> <class name="Address"> <id name="id" column="addressId"> <generator class="native"/> </id> <set name="people" inverse="true"> <key column="addressId"/> <one-to-many class="Person"/> </set> </class>
注意:many-to-one關聯需要將one的一端加入inverse="true";column="addressId"指明了person表的外鍵。
sql輸出:
create table Person ( personId bigint not null primary key, addressId bigint not null ) create table Address ( addressId bigint not null primary key )
2.一對一
基於外鍵關聯的雙向一對一關聯也很常見。
下面例子中person與address的聯系(數據庫用語)是1:1,可以這么理解:
即一個人只能管理一個地方,一個地方只能由一個人管理。
column="addressId"指明了person表的外鍵。
<class name="Person"> <id name="id" column="personId"> <generator class="native"/> </id> <many-to-one name="address" column="addressId" unique="true" not-null="true"/> </class> <class name="Address"> <id name="id" column="addressId"> <generator class="native"/> </id> <one-to-one name="person" property-ref="address"/> </class>
sql輸出:
create table Person ( personId bigint not null primary key, addressId bigint not null unique ) create table Address ( addressId bigint not null primary key )
使用連接表的關聯
使用連接表的關聯通常針對多對多。連接表會是數據中另外建的一張表,來存儲兩個實體的聯系。
這張表有三個字段:本身的id,兩個外鍵分別關聯到兩個實體的主鍵。
下面是student與course的聯系(數據庫用語)是m:n,可以這么理解:
一個學生可以選多門課程,一門課程也有多個學生。
<class name="Student"> <id name="id" column="studentId"> <generator class="native"/> </id> <set name="courses" table="StudentCourse"> <key column="studentId"/> <many-to-many column="courseId" class="Course"/> </set> </class> <class name="Course"> <id name="id" column="courseId"> <generator class="native"/> </id> <set name="students" inverse="true" table="StudentCourse"> <key column="courseId"/> <many-to-many column="studentId" class="Student"/> </set> </class>
注意:<set>增加了table屬性,因此會另外建表。
sql輸出:
create table Student ( studentId bigint not null primary key ) create table StudentCourse ( studentId bigint not null, courseId bigint not null, primary key (studentId, courseId) ) create table Course ( courseId bigint not null primary key )