??? 在上一部分我只講到如何通過數據庫中的表生成映射文件和 POJO 。在這一部分中,我將講解映射文件。
??? 先看看這張表:
???
??????????
在現實的車輛管理系統中,絕對不會把車輛信息和擁有人信息放在一張表中。應該是“一個擁有者”擁有一或多個“車輛”。來看看分解后的表,
PEOPLE
表,設置
OWNER_ID
為
主鍵:
?
???
AUTO_INFO
表,設置
AUTO_ID
為
主鍵:
?
???
為兩表配置主、外鍵關系,設置
PEOPLE
表為主表:
????
????
打開 Eclipse ,為這兩張表生成映射文件。
AutoInfo.hbm.xml :
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
?????? "-//Hibernate/Hibernate Mapping DTD//EN"
?????? "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" >
<hibernate-mapping package="bo">
?????? <class name="AutoInfo" table="AUTO_INFO">
????????????? <id
???????????????????? column="AUTO_ID"
???????????????????? name="Id"
???????????????????? type="integer"
????????????? >
???????????????????? <generator class="vm" />
????????????? </id>
????????????? <property
???????????????????? column="LICENSE_PLATE"
???????????????????? length="20"
???????????????????? name="LicensePlate"
???????????????????? not-null="false"
???????????????????? type="string"
?????????????
?/>
????????????? <many-to-one
???????????????????? class="People"
???????????????????? name="OwnerNo"
???????????????????? not-null="true"
????????????? >
???????????????????? <column name="OWNER_NO" />
????????????? </many-to-one>
?????? </class>
</hibernate-mapping>
|
People.hbm.xml :
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
?????? "-//Hibernate/Hibernate Mapping DTD//EN"
?????? "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" >
<hibernate-mapping package="bo">
?????? <class name="People" table="PEOPLE">
????????????? <id
???????????????????? column="OWNER_ID"
???????????????????? name="Id"
???????????????????? type="integer"
????????????? >
???????????????????? <generator class="vm" />
????????????? </id>
????????????? <property
???????????????????? column="NAME"
???????????????????? length="50"
???????????????????? name="Name"
???????????????????? not-null="false"
???????????????????? type="string"
?????????????
?/>
????????????? <property
???????????????????? column="ADDRESS"
???????????????????? length="1000"
???????????????????? name="Address"
???????????????????? not-null="false"
???????????????????? type="string"
?????????????
?/>
????????????? <set inverse="true" name="AutoInfoSet">
???????????????????? <key column="OWNER_NO" />
???????????????????? <one-to-many class="AutoInfo" />
????????????? </set>
?????? </class>
</hibernate-mapping>
|
以 AutoInfo.hbm.xml 作為詳細分析的例子:
DOCTYPE
定義了這個 XML 文件規范 DTD,可以通過后面的 URL 獲取,或者在 Hibernate 的 CLASSPATH 中獲取。
hibernate-mapping package="bo"
定義了POJO所存在的包
“bo”。
class name="AutoInfo" table="AUTO_INFO"
定義了 POJO 的名稱“AutoInfo”和數據庫中的表名“AUTO_INFO”。
id column="AUTO_ID" name="Id" type="integer"
定義了數據庫表中的主鍵字段,為相應的 POJO 的每個實例包含唯一標識。column為數據庫表字段名,name標識屬性名字,type說明在 POJO 中的類型。另外,還有一個重要標識:unsaved-value,將會在以后用到。
Generator
為每個 POJO 的實例提供唯一標識。一般情況,我們使用
“
native
”
。class表示采用由生成器接口
net.sf.hibernate.id.IdentifierGenerator
實現的某個實例,其中包括:
“
assigned
”
主鍵由外部程序負責生成,在 save() 之前指定一個。
“
hilo
”
通過
hi/lo
算法實現的主鍵生成機制,需要額外的數據庫表或字段提供高位值來源。
“
seqhilo
”
與
hilo
類似,通過
hi/lo
算法實現的主鍵生成機制,需要數據庫中的
Sequence
,適用于支持
Sequence
的數據庫,如
Oracle
。
“
increment
”
主鍵按數值順序遞增。此方式的實現機制為在當前應用實例中維持一個變量,以保存著當前的最大值,之后每次需要生成主鍵的時候將此值加
1
作為主鍵。這種方式可能產生的問題是:不能在集群下使用。
“
identity
”
采用數據庫提供的主鍵生成機制。如
DB2
、
SQL Server
、
MySQL
中的主鍵生成機制。
“
sequence
”
采用數據庫提供的
sequence
機制生成主鍵。如
Oralce
中的
Sequence
。
“
native
”
由
Hibernate
根據使用的數據庫自行判斷采用
identity
、
hilo
、
sequence
其中一種作為主鍵生成方式。
“
uuid.hex
”
由
Hibernate
基于
128
位 UUID 算法 生成
16
進制數值(編碼后以長度
32
的字符串表示)作為主鍵。
“
uuid.string
”
與
uuid.hex
類似,只是生成的主鍵未進行編碼(長度
16
),不能應用在
PostgreSQL
數據庫中
。
“
foreign
”
使用另外一個相關聯的對象的標識符作為主鍵。
property
column="LICENSE_PLATE" length="20"
name="LicensePlate" not-null="false" type="string"
定義了 POJO 中的屬性,分別表示數據庫表中的字段、長度、POJO 屬性名稱以及類型、非空狀態。
many-to-one class="People"
name="OwnerNo
"
not-null="true"
column name="OWNER_NO"
定義了一個持久化對象與另一個持久化對象的關系,這種關聯模型是多對一的關聯。應用在車輛管理系統中,代表著多臺車輛由一個擁有者擁有。分別表示關聯類的名字(由反射機制得到類型)、屬性名稱、非空狀態、字段名。
分析完 AutoInfo.hbm.xml 后,再來看看 People.hbm.xml 。大部分內容都已經在前面出現過,不同的地方是:
<set inverse="true" name="AutoInfoSet">
????????????? <key column="OWNER_NO" />
????????????? <one-to-many class="AutoInfo" />
</set>
|
在車輛管理系統中,代表著一個擁有者擁有多臺車輛。以 java.util.Set類型表示。 inverse用于標識雙向關聯中的
被動方一端。
inverse=false
的一方(主控方)負責維護關聯關系
;在
車輛管理系統
中,
AutoInfo
作為主控方,應該把它設為“
true
”。這就好比你(被動方
one
)在某個聚會上散發了許多名片,但是有可能你不清楚接收者(主動方
many
)的具體背景;這個不要緊,接收者在必要的時候會和你聯系就是了(主動維護關系)。
另外在
set
節點的屬性中還有一個重要標識
:
級聯(
cascade
)關系,指明哪些操作(insert、update、delete)會從
主控方
對象級聯到關聯的對象。
可選值:
all: save()
、
saveOrUpdate()
、
update()
、
delete()
均進行級聯操作。
none
:
所有情況下均不進行級聯操作。
save-update:
在執行
save()
、
saveOrUpdate()
、
update()
時進行級聯操作。
delete
:
只在執行
delete()
時進行級聯操作。
級聯(
cascade
)在
Hibernate
映射關系中是個非常重要的概念。它指的是當主控對象調用
save-update
或
delete
方法時,是否同時對關聯對象(被動方)進行
save-update
或
delete
。在這個映射文件中,當擁有者(
People
)被更新或者刪除時,其所關聯的車輛(
AutoInfo
)可以被修改或刪除,所以應該把級聯關系設置為
cascade=”all”
。
請注意!引用、轉貼本文應注明原作者:Rosen Jiang 以及出處:
http://www.aygfsteel.com/rosen