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