我的 O/R Mapping 之旅(二)

    在上一部分我只講到如何通過數據庫中的表生成映射文件和 POJO。在這一部分中,我將講解映射文件。

    先看看這張表:

                   

 

 

 

在現實的車輛管理系統中,絕對不會把車輛信息和擁有人信息放在一張表中。應該是“一個擁有者”擁有一或多個“車輛”。來看看分解後的表,PEOPLE 表,設置 OWNER_ID 主鍵:

              

              

    AUTO_INFO 表,設置 AUTO_ID 主鍵:

             

   
爲兩表配置主、外鍵關係,設置 PEOPLE 表爲主表:

             

   
爲兩表配置主、外鍵關係,設置 PEOPLE 表爲主表:

             

   
爲兩表配置主、外鍵關係,設置 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>

<?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>

<?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

採用數據庫提供的主鍵生成機制。如DB2SQL ServerMySQL 中的主鍵生成機制。

sequence

採用數據庫提供的 sequence 機制生成主鍵。如 Oralce 中的Sequence

native

Hibernate 根據使用的數據庫自行判斷採用 identityhilosequence 其中一種作爲主鍵生成方式。

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" 

    property column="LICENSE_PLATE" length="20" name="LicensePlate" not-null="false" type="string" 
    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>


<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://blog.csdn.net/rosen

      
   

(請注意!引用、轉貼本文應註明原作者:Rosen Jiang 以及出處:http://blog.csdn.net/rosen

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章