我的 O/R Mapping 之旅(二)

类别:Java 点击:0 评论:0 推荐:

    在上一部分我只讲到如何通过数据库中的表生成映射文件和 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://blog.csdn.net/rosen

本文地址:http://com.8s8s.com/it/it13207.htm