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