在上一部分我只讲到如何通过数据库中的表生成映射文件和 POJO。在这一部分中,我将讲解映射文件。
先看看这张表:
在现实的车辆管理系统中,绝对不会把车辆信息和拥有人信息放在一张表中。应该是“一个拥有者”拥有一或多个“车辆”。来看看分解后的表,PEOPLE 表,设置 OWNER_ID 为 主键:
AUTO_INFO 表,设置 AUTO_ID 为 主键:
为两表配置主、外键关系,设置 PEOPLE 表为主表:
打开 Eclipse,为这两张表生成映射文件。
AutoInfo.hbm.xml:
<?xml version="1.0"?> <hibernate-mapping package="bo"> |
People.hbm.xml:
<?xml version="1.0"?> <hibernate-mapping package="bo"> |
以 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"
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"> |
在车辆管理系统中,代表着一个拥有者拥有多台车辆。以 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”。