數據庫表與表之間的關聯關係,分爲三種一對一、一對多、多對一、多對多。
在通常的數據庫設計的時候一般都是通過表外鍵來建立各種關係,做這些關係一般都是爲了一些級聯操作。
由於Hibernate是把數據庫中表與表之間的關係型數據映射成面向對象型的數據關係,在hibernate中,也做了相應的數據級聯操作的工作。因而可以在數據層來完成數據庫表的關聯,可以在這一層通過面向對象的方式形象的完成級聯操作,這時不需要在數據庫表裏建立複雜的外鍵關聯也可以實現。
在網上和書上看到很多介紹這方面的知識,一般都是按照一對一、一對多、多對一、多對多的順序介紹,爲了容易理解,我通過另一種順序:
一般多對多的實現都是通過第三個表來實現,在hibernate裏也不例外,我們可以分析出這個第三方表與另外兩個表就是多對一的關係。
一對一的關係可以看作是一對多的特殊情況。
一對多與多對一可以看作僅僅是方向的不同而已。
所以我先介紹一對多,然後 一對一,然後多對多。
一對多與多對一關聯關係
在hibernate中關聯關係一般都是通過外鍵來關聯的,(我在學習的時候也有個錯誤的理解,這個外鍵不是在數據庫表上建立的,經過試驗在數據庫中不建立外鍵關係,只在hibernate中設置完全可以實現同樣的效果),這時的關聯可以分爲單向與雙向兩種。
所謂的單向就是說,在兩端中的任一端不知知道另一端的存在,而另一端確清楚的小的另一端;雙向當然就是雙方互知了。
1、單向關聯
在hibernate裏面一對多關聯關係的實現實在“一”的一段映射文件中使用<one-to-many>節點實現的,同時要求在“一”端的POJO使用集合來存儲“多段”的對象。
在以下例子中我將實現一個留言板程序。
先完成數據庫的一部分設計,首先需要一個表來存儲用戶信息,然後還需要一個表來存放留言信息,具體的SQL語句如下(我採用的是MySQL數據庫):
CREATE TABLE `user` (
`usr_id` int(11) NOT NULL auto_increment,
`usr_name` char(20) default NULL,
`usr_psw` char(20) default NULL,
PRIMARY KEY (`usr_id`)
) ENGINE=InnoDB DEFAULT CHARSET=UTF8;
CREATE TABLE `message` (
`msg_id` int(11) NOT NULL auto_increment,
`msg_ttl` char(20) NOT NULL default 0,
`msg_desc` char(50) default NULL,
`msg_date` Date,
`usr_id` int(11)NOT NULL default 0,
PRIMARY KEY (`msg_id`)
) ENGINE=InnoDB DEFAULT CHARSET=UTF8;
顯然這是個一對多的例子,相應的POJO類爲
public class Message {
private int msgId;
private String ttl;
private String desc;
private Date date;
public class UserInfo {
private int userId;
private String name;
private String password;
private IdCard idCard;
private Set messages;
這裏我省了get,set方法
相應的映射文件配置:
<hibernate-mapping>
<class name="xiaojin.hibernate.entity.UserInfo" table="USER">
<id name="userId" type="int" column="usr_id">
<generator class="native"/>
</id>
<property name="name" column="usr_name" type="string" />
<property name="password" column="usr_psw" type="string" />
<set name="messages" order-by="usr_id" cascade="all">
<key column="usr_id" />
<one-to-many class="xiaojin.hibernate.entity.Message" />
</set>
</class>
</hibernate-mapping>
這個配置文件最主要的就是這個節點
<set name="messages" order-by="usr_id" cascade="all">
<key column="usr_id" />
<one-to-many class="xiaojin.hibernate.entity.Message" />
</set>
這個<set>節點意味着POJO UserInfo類裏面定義一個集合,在這個節點中:
<key>:指定多端的外鍵,與一端的主鍵相關聯,即MESSAGE表中的usr_id
<one-to-many>:指定多端的對應的類
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="xiaojin.hibernate.entity.Message" table="MESSAGE">
<id name="msgId" type="int" column="msg_id">
<generator class="native"/>
</id>
<property name="ttl" column="msg_ttl" type="string" not-null="true"/>
<property name="desc" column="msg_desc" type="string" not-null="true"/>
<property name="date" column="msg_date" type="string" />
多對一的映射與上面完全一樣,只不過需要在多的一段進行配置,即在message的應射文件中需要配置<many-to-one>節點:
<many-to-one name="user" column="usr_id" />