我的 O/R Mapping 之旅(二)

时间:2022-01-14 16:36:21

 

    在上一部分我只讲到如何通过数据库中的表生成映射文件和 POJO。在这一部分中,我将讲解映射文件。

 

    先看看这张表:

                    我的 O/R Mapping 之旅(二)

 

在现实的车辆管理系统中,绝对不会把车辆信息和拥有人信息放在一张表中。应该是“一个拥有者”拥有一或多个“车辆”。来看看分解后的表,PEOPLE 表,设置 OWNER_ID 主键:

   我的 O/R Mapping 之旅(二)
 

    AUTO_INFO 表,设置 AUTO_ID 主键:

 

   我的 O/R Mapping 之旅(二)



   
为两表配置主、外键关系,设置 PEOPLE 表为主表:

 

                我的 O/R Mapping 之旅(二)

 

打开 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

采用数据库提供的主键生成机制。如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"

定义了 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”