26
Hibernate 映映映映映映映 ORM 映映—— Hibernate3.3

3 hibernate映射元素和类型

Embed Size (px)

Citation preview

Page 1: 3 hibernate映射元素和类型

Hibernate映射元素和类型

ORM框架—— Hibernate3.3

Page 2: 3 hibernate映射元素和类型

www.sodi.com.cn

Hibernate使用 XML文件来配置对象 - 关系映射,有以下优点: Hibernate既不会渗透到上层域模型中,也不会渗透到下层数据模型中。

软件开发人员可以独立设计域模型,不必强迫遵守任何规范。 数据库人员可以独立设计数据库,不必强迫遵守任何规范 对象 - 关系映射不依赖于任何程序代码,如果需要修改对

象 - 关系映射,只需修改 XML文件,不需要修改任何程序,提高了软件的灵活性,并且使维护更加方便。

使用 XML文件来配置对象 - 关系映射

Page 3: 3 hibernate映射元素和类型

www.sodi.com.cn

持久化类的属性和访问方法

持久化类是指其实例需要被Hibernate持久化到数据库中的类。持久化类通常都是域模型中的实体域类,符合 JavaBean规范。

Hibernate并不要求持久化类必须实现java.io.Serializable接口。

Hibernate要求持久化类必须提供一个无参构造方法。

用户界面

Java应用程序

Customer对象

Hibernate 数据库getXXX()

setXXX()

Page 4: 3 hibernate映射元素和类型

www.sodi.com.cn

基本类型属性和包装类型属性

在持久化类中,既可以把属性定义为基本类型,也可以定义为包装类型,它们对应相同的Hibernate映射类型(请参考Hibernate映射类型对照表 .xlsx )。

基本类型和包装类型各有优缺点。基本类型的优点是:使用方便,对于数字类型,可以直接进行数学运算;缺点在于无法表达 null值。

包装类型进行数学运算时稍微麻烦一些,但是与 SQL数据类型之间具有更直接的对应关系。

对于持久化类的OID,推荐使用包装类型。

Page 5: 3 hibernate映射元素和类型

www.sodi.com.cn

Hibernate访问持久化类属性的策略

在对象 - 关系映射文件中,<property>元素的access属性用于指定Hibernate访问持久化类的属性的方式。它有两种可选值: property:这是默认值,表明Hibernate通过对应的

setXXX() 和 getXXX()方法来访问类的属性。这是优先推荐的方式。

field:表明Hibernate运用 Java反射机制直接访问类的属性。

Page 6: 3 hibernate映射元素和类型

www.sodi.com.cn

在持久化类的访问方法中加入程序逻辑

在持久化类的访问方法中,可以加入程序逻辑,下面举例说明。 在 Customer类的 getName() 和 setName()方法中加入程序逻辑。

在 Customer类的 setSex()方法中加入数据验证逻辑。

Page 7: 3 hibernate映射元素和类型

www.sodi.com.cn

控制 insert 和 update语句 (1)

Hibernate在初始化阶段,就会根据映射文件的映射信息,为所有的持久化类预定义以下 SQL语句insert语句、 update语句、 delete语句和根据OID来检索持久化类实例的 select语句。例如 Salgrade类的语句如下:INSERT INTO SALGRADE(GRADE, LOSAL, HISAL) VALUES(?, ?, ?);UPDATE SALGRADE SET LOSAL=?, HISAL=?;DELETE FROM SALGRADE WHERE ID=?;SELECT GRADE,LOSAL,HISAL FROM SALGRADE WHERE GRADE=?;

Page 8: 3 hibernate映射元素和类型

www.sodi.com.cn

控制 insert 和 update语句 (2)

以上 SQL语句中的问号代表 JDBC PreparedStatement中的参数。这些 SQL语句都存放在 SessionFactory的缓存中,当执行 Session 的save() 、 update() 、 delete() 和 load()方法时,将从缓存中找到相应的预定义 SQL语句,再把具体的参数值绑定到该 SQL语句中。

而 HQL 或 QBC查询对应的 select语句必须在执行该代码时才能动态生成。

在对象 - 关系映射文件中,通过配置<class> 和<property>元素的一些属性,可以控制 insert 和update语句的生成,具体参考Hibernate_Reference中对象 /关系数据库映射基础 (Basic O/R Mapping)一章。

Page 9: 3 hibernate映射元素和类型

www.sodi.com.cn

用于控制 insert 和 update语句的映射属性

映射属性 作用<property>元素的insert属性

false,在 insert语句中不包含该字段,即不能被插入 ; 默认值为 true

<property>元素的update属性

false,在 update语句中不包含该字段,即不能被修改 ,默认值为 true

<class>元素的mutable属性

false,等价于所有的<property>元素的 update 为 false,即不能被修改 ,默认值为 true

<property>元素的dynamic-insert属性

如果为 true,表示当更新一个对象时,会动态生成 insert语句,只能取值不为 null时,才会包含到 insert语句中,默认值为 false

<property>元素的dynamic-update属性

如果为 true,表示当更新一个对象时,会动态生成 update语句,只能取值不为 null时,才会包含到 update语句中,默认值为 false

<class>元素的dynamic-insert属性

如果为 true,所有<property>的 dynamic-insert属性为 true,表示当更新一个对象时,会动态生成 insert语句,只能取值不为 null时,才会包含到 insert语句中,默认值为 false

<class>元素的dynamic-update属性

如果为 true,所有<property>的 dynamic-update属性为 true,表示当更新一个对象时,会动态生成 insert语句,只能取值不为 null时,才会包含到 update语句中,默认值为 false

Page 10: 3 hibernate映射元素和类型

www.sodi.com.cn

处理 SQL引用标识符

在 SQL语法中,标识符是指用于为数据库表、视图、字段或者索引等命名的字符串,常规标识符不包含空格,也不包含特殊字符,因此无需使用引号括起来。

有时候,特别是在遗留数据库中,你会遇到包含奇怪字符或者空格的标识符,或者你希望强制区分大小写。或者,如果依赖Hibernate的默认配置, Java中的类名或者属性名可能被自动转化为数据库管理系统中不允许的表名或者列名。那么,就可以使用引用标识符。

用反引号括起来是一种方案,但它是Hibernate的一个实现细节,而不是 JPA规范的一部分,所以一般情况下,应该考虑重新命名表名和列名。

Page 11: 3 hibernate映射元素和类型

www.sodi.com.cn

映射对象标识符

Java语言按内存地址来识别或区分同一个类的不同对象,而关系数据库按主键值来识别或区分同一个表的不同记录。

Hibernate使用对象标识符(OID)来建立内存中的对象和数据库表中记录的对应关系,对象的OID和数据库表的主键对应。

为了保证持久化对象的OID的唯一性和不可变性,应该让 Hibernate,而不是应用程序为OID 赋值。

Page 12: 3 hibernate映射元素和类型

www.sodi.com.cn

<id>元素

被映射的类 必须 定义对应数据库表主键字段。大多数类有一个 JavaBeans 风格的属性, 为每一个实例包含唯一的标识。<id> 元素定义了该属性到数据库表主键字段的映射。例如:

<id>元素可选的属性可以参考Hibernate_Reference。

<id name="productGuid" type="java.lang.Integer"><column name="ProductGUID" /><generator class="native" />

</id>

Page 13: 3 hibernate映射元素和类型

www.sodi.com.cn

<generator> 子元素

<generator> 子元素用来设定标识符生成器。Hibernate提供了标识符生成器接口

IdentifierGenerator,开发者可以通过实现该接口创建自己的标识符生成器。

当然,Hibernate提供了很多内置的实现,接下来我们逐个介绍。

Page 14: 3 hibernate映射元素和类型

www.sodi.com.cn

assigned标识符生成器

让应用程序在 save()之前为对象分配一个标示符。这是 <generator>元素没有指定时的默认生成策略。

适用范围: 由于 assigned生成标识符的机制不依赖于底层数据库系

统,因此它适用于所有的数据库系统。 主键由应用程序生成而非 Hibernate来生成。

Page 15: 3 hibernate映射元素和类型

www.sodi.com.cn

increment标识符生成器

Hibernate 启动时,这个生成器读取表的最大(数字)主键列值,并且每次插入一个新行时值就增加 1 。生成的标识符类型为 long 、 short或者 int。

适用范围: 由于 increment生成标识符的机制不依赖于底层数据库系

统,因此它适用于所有的数据库系统。 适用于只有单个Hibernate应用进程访问同一个数据库的

场合,在集群环境下不推荐使用它。 OID必须为 long 、 int 或 short类型,如果OID定义为其他类型,在运行时会抛出IdentifierGenerationException。

Page 16: 3 hibernate映射元素和类型

www.sodi.com.cn

identity标识符生成器

Identity标识符生成器由底层数据库来负责生成标识符,它要求底层数据库将主键定义为自动增长字段类型。

适用范围: 由于 identity生成标识符的机制依赖于底层数据库系统,因此,要求底层数据库系统必须支持自动增长字段类型。支持自动增长字段类型的数据库包括:DB2 、 MySQL 、 MS SQL Server 、 Sybase 、 HSQLDB 和 Informix等。

OID必须为 long 、 int 或 short类型,如果OID定义为其他类型,在运行时会抛出IdentifierGenerationException。

Page 17: 3 hibernate映射元素和类型

www.sodi.com.cn

sequence标识符生成器

sequence标识符生成器利用底层数据库提供的序列来生成标识符。

适用范围: 由于 sequence生成标识符的机制依赖于底层数据库系统的序列,因此,要求底层数据库系统必须支持序列。支持序列的数据库包括:Oracle 、 DB2 、 SAP DB 和PostpreSQL等。

OID必须为 long 、 int 或 short类型,如果OID定义为其他类型,在运行时会抛出IdentifierGenerationException。

Page 18: 3 hibernate映射元素和类型

www.sodi.com.cn

hilo标识符生成器

hilo标识符生成器由 Hibernate 按照一种 hign/low算法来生成标识符,它从数据库的特定表的字段中获取 hign值,并通过添加本地的低值被变成唯一。

适用范围: 由于 hilo生成标识符的机制不依赖于底层数据库系统,因此适用于所有的数据库系统。

OID必须为 long 、 int 或 short类型,如果OID定义为其他类型,在运行时会抛出IdentifierGenerationException。

hign/low算法生成的标识符只能在一个数据库中保证唯一。

Page 19: 3 hibernate映射元素和类型

www.sodi.com.cn

uuid标识符生成器

uuid标识符生成器使用一个 128 位的全局唯一标识符( Universally Unique Identifier , UUID)算法生成字符串类型的标识符。UUID包含本机的 IP 地址、本机 JVM的信息,相对于同一时空中的所有机器都是唯一的。

适用范围: uuid标识符生成器由 Hibernate维护并生成 uuid值,不依赖于底层数据库的实现细节,因而可以适用于所有数据库。

由于UUID的值是完全随机的,因此在数据库中,不能确定记录的顺序。

仅当你全局地需要唯一标识符时才使用这个生成器策略,并且是我们在不使用 JNI的前提下的能做的最好实现了。

Page 20: 3 hibernate映射元素和类型

www.sodi.com.cn

guid标识符生成器

guid标识符生成器利用底层数据库生成 guid的函数来生成字符串类型的标识符。

适用范围: 由于 guid生成标识符的机制依赖于底层数据库系统,因此,要求底层数据库必须支持 guid。目前支持 guid的数据库有:Oracle 、 MS SQL Server 、 MySQL 、 Sybase等。

由于UUID的值是完全随机的,因此在数据库中,不能确定记录的顺序。

仅当你全局地需要唯一标识符时才使用这个生成器策略。

Page 21: 3 hibernate映射元素和类型

www.sodi.com.cn

使用 uuid标识符或 guid标识符生成器时注意uuid/guid标识符生成器使用 32 位 16进制字符串,需要占用更多的空间,索引的效率也比较低,因此,一般都会在表中加一个时间类型或是 int类型的索引,可以弥补以 uuid/guid 作为主键带来的性能损失。

Page 22: 3 hibernate映射元素和类型

www.sodi.com.cn

native标识符生成器

native标识符生成器依据底层数据库对自动生成标识符的支持能力,来选择使用identity 、 sequence 或 hilo标识符生成器。 native能自动判断底层数据库提供的生成标识符的机制。

适用范围: 由于 native能根据底层数据库系统的类型,自动选择合适的标识符生成器,因此很适合与跨数据库平台开发,即同一个 Hibernate应用需要连接多种数据库系统的场合。

OID必须为 long 、 int 或 short类型,如果OID定义为其他类型,在运行时会抛出IdentifierGenerationException。

Page 23: 3 hibernate映射元素和类型

www.sodi.com.cn

映射复合(或称联合)主键——嵌入式

如果表使用联合主键,你可以映射类的多个属性为标识符属性。 <composite-id>元素接受 <key-property> 属性映射和<key-many-to-one>属性映射作为子元素。 例如:

值得注意的是: 持久化类必须实现 java.io.serializable接口,并重写

equals() 和 hashCode()方法。 必须初始化持久化类的实例,填充它的标识符属性,再

load() 组合关键字关联的持久状态。

<composite-id> <key-property name="medicareNumber"/> <key-property name="dependent"/></composite-id>

Page 24: 3 hibernate映射元素和类型

www.sodi.com.cn

映射复合(或称联合)主键——组件式

映射复合主键的另一种方式是使用一个组件作为一个实体类的标识符。 例如:

你的组件类必须满足以下要求: 必须实现 java.io.Serializable接口。 包含所有<key-property>元素指定的属性。 必须重新实现 equals() 和 hashCode()方法 , 始终和组合关

键字在数据库中的概念保持一致。在持久化类中不必定义 <key-property>元素指定的属性,而是定义 id属性,类型为MedicareId。

<composite-id name="id" class="MedicareId"> <key-property name="medicareNumber"/> <key-property name="dependent"/></composite-id>

Page 25: 3 hibernate映射元素和类型

www.sodi.com.cn

Demo——使用MyEclipse 自动化Hibernate1. 添加Hibernate 支持。2. 利用Hibernate Reverse Engineering 完成对象 - 关系映射文件和 POJO类的创建。

Page 26: 3 hibernate映射元素和类型

www.sodi.com.cn