知識的準備:
(參考:湯陽光Hibernate3.6(基礎))
一、淺談javaBean之間的關係
存在的關係:
1.關聯(一對一、一對多、多對一、多對多)
2.聚合/組合(最後考慮)
3.繼承
所以,映射主要分爲關聯映射、繼承映射、其它映射
二、hibernate映射研究的就是持久化對象那一整流程
通過配置文件來控制映射
三個實體中,只要確定兩個,就能得到第三個;
此文,主要是從javaBean+配置---------------自動生成-------------table()
需要自動生成,在開發階段最好在hibernate.cfg.xml中配
<!-- bean自動生成table -->
<property name="hbm2ddl.auto">create-drop</property>
<!-- 打印sql語句 -->
<property name="show_sql">true</property>
整理思路:
java實體由兩部分組成:數據和關係;同理,數據庫中的表也一樣。
數據部分在不同的系統中,存儲大同小異,只需要關係編碼問題就OK了
但關係部分,在不同的系統中,有很大的差別;而hibernate就是解決,javaObject與DBTable之間的映射,
那麼,我們的明白,在javaObject與DBTable具體對於關係是怎麼存儲的;
javaObject中數據以對象爲基本單位,
主要有兩種類型:一對一,對象之間相互通過以對方對象爲屬性來建立聯繫;
一對多,建立集合,對象的集合。
Db table中關係是通過主外鍵來建立聯繫的
兩者之間的映射,就是問題所在
正式研究關係
在hibernate中,要進行object與table之間的轉換,對object我們不需要進行任何處理,而僅僅只需要對改變xml的配置文件即可。
而我們研究的重點也就是配置文件如何將不同的關係進行配置。
三、關係配置
1.最基本的配置,(假設對象之間沒有任何關係,其它都爲默認設置)
參見下面代碼
在實體類包目錄下建立,如本例
首先:
1)在com.tjcu.domain下建User
public class User {
private int id;
private String name;
private Date birthday;
//必須的
public User() {
}
//get/set略
2)在com.tjcu.domain目錄下建立User.hbm.xml文件
<!-- 創建object與table之間的映射 -->
<!-- 第一步,導入包命 -->
<hibernate-mapping package="com.tjcu.domain">
<!-- 第二步,建立class與table之間的映射 -->
<class name="User" table="user">
<!-- 第三步,建立主鍵映射 ,-->
<id name="id" column="id" >
<!-- 注意了,更具不同的需求,選擇不同的主鍵生成器,參考文檔 -->
<generator class="native" /> <!-- "native"一種主鍵生成器,使用hibernate內置id生成 -->
</id>
<!-- 第四步,將所有的屬性都建立映射 -->
<property name="name" column="name" />
<property name="birthday" column="birthday" />
</class>
</hibernate-mapping>
3)在hibernate.cfg.xml文件中添加
<mapping resource="com/tjcu/domain/User.hbm.xml"/>
以上就是一個最基本的配置
其中有一個難點:就是主鍵的生成方式
{
1.爲什麼有這樣奇葩的主鍵生成器啊?
因爲java中判斷同一class而不同的object是通過內存地址來判斷的,而table中是以id來判斷的。
2.具體的主鍵生成器
native: 對於 oracle 採用 Sequence 方式,對於MySQL 和 SQL Server 採用identity(自增主鍵生成機制),native就是將主鍵的生成工作交由數據庫完成,hibernate不管 (很常用)。
identity: 使用SQL Server 和 MySQL 的自增字段,這個方法不能放到 Oracle 中,Oracle 不支持自增字段,要設定sequence(MySQL 和 SQL Server 中很常用)。
sequence: 調用底層數據庫的序列來生成主鍵,要設定序列名,不然hibernate無法找到。
uuid: 採用128位的uuid算法生成主鍵,uuid被編碼爲一個32位16進制數字的字符串。佔用空間大(字符串類型)。hilo: 使用hilo生成策略,要在數據庫中建立一張額外的表,默認表名爲hibernate_unique_key,默認字段爲integer類型,名稱是next_hi(比較少用)。
foreign: 使用另外一個相關聯的對象的主鍵。通常和<one-to-one>聯合起來使用
我就用過這幾個,還有別的,根據不同的需求,來查API;一般沒有限制,我都採樣native。
}
2.關聯配置
單項關聯:僅僅建立從Order到Customer的多對一關聯,即僅僅在Order類中定義customer屬性。或者僅僅建立從Customer到Order的一對多關聯,即僅僅在Customer類中定義orders集合。
雙項關聯:既建立從Order到Customer的多對一關聯,又建立從Customer到Order的一對多關聯
1)一對多/多對一
many-to-one屬性:
*name:設定待映射的持久化類的名字。
*column:設定和持久化類的屬性對應的表的外鍵。
*class:設定持久化類的屬性的類型。
*not-null:是否允許爲空。
2)一對一
必須的區分主次
對於基於外鍵的1-1關聯,其外鍵可以存放在任意一邊,在需要存放外鍵一端,增加 many-to-one 元素。爲 many-to-one元素增加 unique=“true” 屬性來表示爲1-1關聯,並用name屬性來指定關聯屬性的屬性名
<many-to-one name="depart" column="depart_id" />
另一端需要使用one-to-one元素,該元素使用 property-ref(可以不加) 屬性指定使用被關聯實體主鍵以外的字段作爲關聯字段
<!-- 一對一 -->
<one-to-one name="person" constrained="true" />
3)繼承
Hibernate支持三種繼承映射策略:
¨ 每個具體類一張表(table per concrete class) 將域模型中的每一個實體對象映射到一個獨立的表中,也就是說不用在關係數據模型中考慮域模型中的繼承關係和多態。
¨ 每個類分層結構一張表(table per class hierarchy) 對於繼承關係中的子類使用同一個表,這就需要在數據庫表中增加額外的區分子類類型的字段。
¨ 每個子類一張表(table per subclass) 域模型中的每個類映射到一個表,通過關係數據模型中的外鍵來描述表之間的繼承關係。這也就相當於按照域模型的結構來建立數據庫中的表,並通過外鍵來建立表之間的繼承關係。
比較:
具體實現細節略了……
4)組成關係(Component)映射
組件屬性的意思是持久化類的屬性既不是基本數據類型,也不是 String 字符串,而是某個組件變量,該組件屬性的類型可以是自定義類。
¨ 顯然無法直接用 property 映射 name 屬性。爲了映射組件屬性, Hibernate 提供了component 元素。
¨ 每個 component 元素映射一個組件屬性,組件屬性必須指定該屬性的類型,component 元素中的 class 屬性用於確定組件的類型。