当前位置:首页 >> 其它课程 >>

传智播客Hibernate


—高级软件人才实作培训专家! Hibernate入门
?

案例

Customer类
Hibernate

BusinessService类
Hibernate API Hibernate配置文件

对象关系型映射

关系数据库

>Customers表
北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate入门
?

创建配置文件

hibernate.dialect=net.sf.hibernate.dialect.OracleDialect hibernate.connection.driver_class=oracle.jdbc.driver.OracleDriver hibernate.connection.url=jdbc:oracle:thin:peopres/peopres@127.0.0.1: 1521:oracle9 hibernate.connection.username=peopres hibernate.connection.password=peopres hibernate.show_sql=true

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate入门
?

创建持久化类
public class Customer implements Serializable { private static final long serialVersionUID = 5431991012351413505L; private Long id; private String name; private String email; ……

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate入门
?

创建数据库
drop database if exists SAMPLEDB; create database SAMPLEDB; use SAMPLEDB; create table CUSTOMERS ( ID bigint not null primary key, NAME varchar(15) not null, EMAIL varchar(128) not null, PASSWORD varchar(8) not null, PHONE int , ADDRESS varchar(255), SEX char(1) , IS_MARRIED bit, DESCRIPTION text, IMAGE blob, BIRTHDAY date, REGISTERED_TIME timestamp ); 北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate入门
?

创建对象-关系映射文件
<hibernate-mapping> <class name="mypack.Customer" table="CUSTOMERS"> <!--id 主键 --> <id name="id" column="ID" type="long"> <generator class="increment" /> </id> <!-- 名称 --> <property name="name" column="NAME" type="string" not-null="true" /> …… </class> </hibernate-mapping>

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate入门
?

把customer持久化类映射到customers表
<class>:类和表的映射 <class name="mypack.Customer“ table="CUSTOMERS"> <id>:持久化类的OID和表主键映射

<id name="id" column="ID" type="long"> <generator class="increment" /> </id>

<property> <property name="email" column="EMAIL" type="string" not-null="true" />
北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate入门
?

java、hibernate、sql类型对应关系
Customer类属 性 java hibernate Cutomers字段名 Sql类型

Name
Phone Sex Married Description image

java.lang.String
int char boolean java.lang.String byte[]

string
int character boolean text binary

NAME
PHONE SEX IS_MARRIED DESCRIPTION IMAGE

Varchar(15)
INT CHAR(1) BIT CLOB BLOB

birthday
registeredTime

java.sql.Date
java.sql.TimeStamp

date
timestamp

BIRTHDAY
REGISTERED_TIM E

DATE
TIMESTAMP

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate入门
?

通过API操作数据库

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate入门
?

通过API操作数据库

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate入门
?

Hibernate初始化

1、创建configuration对象,把hibernate.properties文件读入内存。 2、add(……)把映射文件读入内存 3、buildSessionFactory()数据源。重量级对象。
北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate入门
?

Hibernate初始化

?

访问Session接口
save() update() delete() load() find()

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate入门
businessService sessionFactory session transaction 1: openSession()

2: beginTransaction 3: save delete find update 4: commit 5: close

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Java对象持久化概述
Hibernate是什么
连接java应用程序和关系型数据库的中间件 对JDBC API封装,负责对象持久化 位于持久化层,封装所有的数据访问细节,使业 务逻辑层更关注于业务逻辑。 一种ORM映射工具。

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Java对象持久化概述
?

应用程序的分层体系结构

应用程序层

表述层

数据库
双层体系结构

业务逻辑程序层
数据库
三层体系结构

表述层:提供与用户交互的GUI。 业务逻辑层:实现各种业务逻辑。 数据库层:负责存放和管理应用的持久性数据。
北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Java对象持久化概述
?

应用程序的分层体系结构

? Java应用的持久化层
表述层 业务逻辑层

表述层
业务逻辑层 持久化层

数据库层

数据库层
北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Java对象持久化概述
?

Hibernate中间件特性
应用1 业务逻辑层 应用2 业务逻辑层 持久化层 (hibernate) 应用3 业务逻辑层

数据库1

数据库2

数据库3

持久化层封装了数据访问的细节,为业务逻辑层提供了面向对象的API。完善的持久化层应该 达到的目标: 1.代码重用性高,可完成所有的数据访问操作。 2.如果需要的话,能够支持多种数据库平台。 3.具有相对独立性,当持久化层变化时,不会影响上层实现。 北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Java对象持久化概述
?

软件模型

?

概念模型:模拟问题域中的真实实体。描述每个实体的 概念和属性及实体间关系。不描述实体行为。实体间的 关系有一对一、一对多和多对多。

客户
Name age
1 *

订单
orderNumber price

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Java对象持久化概述
?

软件模型

?

关系数据模型:在概念模型的基础上建立起来的,用于 描述这些关系数据的静态结构。有以下内容组成: 1.若干表 2.表的所有索引 3.视图 4.触发器 5.表与表之间的参照完整性
Customers表 ID<PK> NAME AGE
ORDERS表 ID<pk> CustomerID<fk> Order_number price
北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Java对象持久化概述
?

软件模型

? 域模型:在软件的分析阶段创建概念模型,在
软件设计阶段创建域模型。 组成部分: 1.具有状态和行为的域对象。 2.域对象之间的关联。

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Java对象持久化概述
?

软件模型

?

域对象(domain object):构成域模型的基本元素就是域对象。 对真实世界的实体的软件抽象,也叫做业务对象(Business Object(BO)).域对象可代表业务领域中的人、地点、事物或 概念。 域对象分为以下几种: 实体域对象:通常是指业务领域中的名词。 (plain old java object)。 过程域对象:应用中的业务逻辑或流程。依赖 于实体域对象,业务领域中的动词。如 发出订单、登陆等。 事件域对象:应用中的一些事件(警告、异常)。
北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Java对象持久化概述
?

软件模型

?

域对象间的关系 1.关联:类间的引用关系。以属性定义的方式表现。

Order

Customer

关联可分为一对一、一对多和多对多。还可分为单项关联和双向关联。
北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Java对象持久化概述
?

软件模型

?

域对象间的关系 依赖:类之间访问关系。无需定义成属性。在A中访问B中的 方法或属性,或者A负责实例化B。

BusinessService

Customer

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Java对象持久化概述
?

软件模型

?

域对象间的关系 3.聚集(Aggregation):整体与部分的关系。例人与手的 关系。部分类的对象不能单独存在,他的生命周期依赖 于整体类的对象的生命周期,整体消失时,部分也随之 消失。

Person hand:set

Hand ……

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Java对象持久化概述
?

软件模型

?

域对象间的关系 4.一般化(Generalization):类之间继承关系。
Employee name

HourEmployee rate

SalaryEmployee salary

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Java对象持久化概述
?

软件模型

?

域对象的持久化概念 实体域对象在内存中创建后,不能永久存在。将实体域 对象永久保存起来,就是持久化的过程。通常只有实体 域对象需要持久化,过程域对象和事件域对象一般不需 要持久化。广义持久化指增、删、改、查。
内存
持久化

Customer对象

数据库
重新加载到内存

order对象

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Java对象持久化概述
?

ORM简介
对象-关系映射(ORM,即Object-Relation Mapping). 指单个组件中负责所有实体域对象的持久化,封装数据访问细节。

业务逻辑层

域模型 (对象、属性、关联、继承和多态)

ORM API 持久化层

参照

ORM 实现

对象-关系映射文件 (xml)

数据库层

关系数据模型 (表、字段、索引、主键和外键) ORM 充当业务逻辑层和数据库层之间的桥梁 北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Java对象持久化概述
?

ORM简介

?

对象-关系映射的概念
面向关系概念
表 表的行(记录) 表的列(字段) 关系数据模型 Customer类 id name homeAddress comAddress Customer类 ID …… HOME_PROVINCE HOME_CITY …… COM_PROVINCE COM_CITY ……

面向对象概念
类 对象 属性 域模型 Address类 Province city street zipcode

注:域模型中类的数目要比关系数据模型中 表的数目多。 北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Java对象持久化概述
?

ORM简介

?

ORM中间件的使用方法 采用元数据来描述对象-关系映射细节,元数据通常采用xml格 式,并存放在专门的对象-关系映射文件中。只要配置了持久 化类与表的映射关系,orm中间件在运行时就能够参照映射 文件的信息,把域对象持久化到数据库中。
public void deleteCustomer(Customer c){ Session session = getSession(); session.delete(c); } 执行步骤如下: 1.运用反射机制,获得Customer对象的Customer.class类。 2.参照映射文件得到Customer类对应的表的信息,以及和Customer类关联的类以及 相应的表信息。 3.根据以上信息生成SQL语句。 4.调用hibernate API,执行该语句。 北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Java对象持久化概述
?

Hibernate API简介

Hibernate对JDBC做了轻量级的封装。所谓轻量级是 指Hibernate并没有完全封装JDBC,java应用既可以 通过HibernateAPI来访问数据库,还可直接通过JDBC API访问数据库。

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Java对象持久化概述
?

Hibernate API简介

?

Hibernate核心接口 1.Configuration 配置hibernate,根启动hibernate,创建 sessionFactory对象。 2.SessionFactory 初始化hibernate,充当数据源代理,创建 session对象。线程安全的,可被多个线程共享。重量级的, 需要一个很大的缓存,用于存放于定义的sql语句和映射元数 据等。用户还可为它配置一个缓存插件,称为二级缓存。 3.Session 使用最广泛,也被称为持久化管理器,它提供和持久 化相关的操作。增、删、改、查等。不是线程安全的,避免多 个线程共享。轻量级的,创建和销毁不需要消耗太多资源。 Session中有一个缓存,称为一级缓存。存放当前工作单元加 载的对象。
北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Java对象持久化概述
?

Hibernate API简介

? Hibernate核心接口(续)
4.Transaction hibernate数据库事务接口, 它对底层的事务接口作了封装.底层事务接 口包括:
JDBC API JTA(java Transaction API) CORBA(common object request Broker architecture)

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Java对象持久化概述
?

Hibernate API简介

?

Hibernate核心接口(续) 5.Query和Criteria接口:都是查询接口,query实例 包装了HQL查询语句,hql是面向对象的,他引用类 名及类的属性名,而不是表名和字段名。Criteria接 口完全封装了基于字符串形式的查询语句,比 query接口更面向对象,他擅长执行动态查询。 sessoin接口的find方法也具有数据查询功能,但他 只是执行一些简单的hql查询语句的快捷方式,远没 有query接口功能强大。

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Java对象持久化概述
?

Hibernate API简介

?

Hibernate映射类型接口 1.PrivateType类:映射java基本数据类型,包括 ByteType、ShortType、IntegerType、 LongType、FloatType、DoubleType、 CharactorType、BooleanType。 2.DateType:映射java日期类型。 3.BinaryType:映射Byte[]类型。
Query.setParameter(“name”,”name”,Hibernate.STRING)

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Java对象持久化概述
?

Hibernate API简介

? 可供扩展的接口

hibernate提供的多数功能是可配置的,允许用 户选择适当的内置策略。如可配置如下数据库 方言:
hibernate.dialect=net.sf.hibernate.dialect.MySQLDialect hibernate.dialect=net.sf.hibernate.dialect.OracleDialect hibernate.dialect=net.sf.hibernate.dialect.SybaseDialect

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Java对象持久化概述
?

Hibernate API简介

? 可供扩展的接口

如果hibernate内置的策略不能满足需求时,允 许用户自定义实现接口或扩展特定的类。 Hibernate的扩展点包括: 主键生成策略:IdentifierGenerator sql方言:Dialect抽象类 缓存机制:cache和cacheprovider接口 jdbc连接管理器:connectionprovider等
北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Java对象持久化概述
?

小结
表现层 业务逻辑层
实体域对象 (业务数据) 过程域对象 (业务逻辑)

持久化层(orm中间件、负责封装数据访问细节) 数据库层
北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 对象-关系映射基础
本章解决的问题 1.持久化类没有getXXX和setXXX方法。 2.持久化类的属性在库中没有对应的字段,或 字段没有对应的属性 3.控制hibernate的insert、update语句。 4.设置从持久化类映射到数据库表,以及持久 化类的属性映射到数据库表的字段的命名策 略。
北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 对象-关系映射基础
?

持久化类的属性及访问方法
Hibernate中持久化类的访问者有两个: 1.Java应用程序 2.hibernate(何时调用get、set方法?)
Customer对象

用户 界面

Java 应用程序

getXXX()方法 setXXX()方法

hibernate

数据库

Java应用程序不能访问持久化类的private方法,而hibernate没有这 个限制,它可以访问各种级别的方法。
北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 对象-关系映射基础
?

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

? 基本数据类型和包装类型

基本数据类型和包装类型对应的hibernate映射 类型相同。
<property name=“price” type=“double” column=“PRICE” /> 基本类型可直接运算、无法表达null、数字类型的默认值为0。 包装类默认值是null。当对于默认值有业务意义的时候需要使用包装类。

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 对象-关系映射基础
?

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

?

Hibernate访问持久化类属性的策略 1.propertye 默认值:表明hibernate通过getXXX和 setXXX来访问类属性。推荐使用。提高域模型透明性。 2.field:hibernate通过java反射机制直接访问类属性。对于没有 javabean方法的属性可设置该访问策略。
<property name=“name” access=“field” />

除了设置property属性的access为field和property之外 还可以自定义访问策略,需要创建实现net.sf.hibernate. property.PropertyAccessor接口的类。

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 对象-关系映射基础
?

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

? 在持久化类的方法中加入程序逻辑
class Customer{ ….. private String firstname ; private String lastname ; public String getName(){ return firstname + “ ” + lastname ; } public void setName(String name){ StringTokenizer t = new StringTokenizer(name); firstname = t.nextToken(); lastname = t.nextToken(); } }

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 对象-关系映射基础
?

持久化类的属性及访问方法 ? 在持久化类的方法中加入程序逻辑 在customer.hbm.xml文件中无需映射firstname和lastname属 性,而是映射name属性。
<property name =“name” column=“NAME” /> 尽管类中并没有name属性,由于hibernate不是直接访问 Name属性,而是调用get、set方法,因此建立了 Firstname、Lastname和表之间的联系。
Customer类 firstname lastname Hibernate getName() CUSTOMERS表 Name字段

setName()
北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 对象-关系映射基础
?

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

? 在持久化类的方法中加入程序逻辑
不管在类中是否存在name属性,只要在 Customer.hbm.xml文件中映射了name属性, 在hql语句中就能访问他。
Session.find(“from customer as c where c.name=?tom?”) 如果改成: <property name=“name” column=“NAME” access=“field”> 后过如何?

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 对象-关系映射基础
?

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

?

设置派生属性 利用<property>元素的formula属性,用来设置一个sql表达式, hibernate将根据它来计算出派生属性的值。

<property name=“totalprice” formula=“(select sum(o.PRICE) from ORDERS o where o.CUSTOMER_ID=ID)” /> <property name=“unitprice” formula=“BASE_PRICE*QUANTITY” />

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 对象-关系映射基础
?

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

?

控制insert、update语句
作用 若为false,在insert语句中不包含该字段,该字段永远不能被插入。 默认值true。 若为false,update语句不包含该字段,该字段永远不能被更新。默认 值为true。 若为false,等价于所有的<property>元素的update属性为false, 整个实例不能被更新。默认为true。 若为true,等价于所有的<property>元素的dynamic-insert为 true,保存一个对象时,动态生成insert语句,语句中仅包含取值不为 null的字段。默认false。 若为true,等价于所有的<property>元素的dynamic-update为 true,更新一个对象时,动态生成update语句,语句中仅包含取值不为 null的字段。默认false。

映射属性 <property> insert属性 <property> update属性 <class> mutable属性 <class> dynamic-insert属 性 <class> dynamic-update属 性

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 对象-关系映射基础
?

处理sql引用表示符
在SQL语法中,表示符是指用于为数据库表、视图、字段 或索引等名字的字符串,常规表示符不包括空格,也不包 含特殊字符,因此无需使用引用符号。如果数据库表名或 列名包含特殊字符,可以使用引用表示符。
<property name=“description” column=“`CUSTOMER DESCRIPTION`” />

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 对象-关系映射基础
?

设置类的包名 如果在一个映射文件中包含多个类,并且这些类位于同一个 包中,可以设置<hibernate-mapping>元素的package属性, 避免为每个类提供完整的类名。
<hibernate-mapping> <class name=“mypack.customer” table=“cu..” > …… </class> <class name=“mypack.Order” table=“orders” > …… </class> </hibernate-mapping>

<hibernate-mapping package=“mypack”> <class name=“customer” table=“cu..” > …… </class> <class name=“Order” table=“orders” > …… </class> </hibernate-mapping>

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 映射对象标识符
Java按地址区分同一个类的不同对象. 关系数据库用主键区分同一条记录. Hibernate使用OID来建立内存中的对象和数据库中记录的对应关 系。对象的OID和数据库的表的主键对应。为保证OID的唯一性,应 该让Hibernate来为OID付值。

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 映射对象表示符
?

关系数据库按主键区分不同记录
主键必备条件: 1. 不允许null 2.唯一,不重复 3.之永远不会改变 自然主键:把具有业务含义的字段作为主键叫做自然主 键。

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 映射对象表示符
?

关系数据库按主键区分不同记录

?

把主键定义为自动增长类型

?

在my SQL中,把字段设为auto_increment类型,数据库会自 动为主键付值。 在ms SQL server中,把字段设为identity类型,数据库会自 动为主键付值。

从序列(sequence)中获取自动增长的描述符 create sequence seq_customer increment by 2 start with 1 insert into customers values(seq_customer.curval,?..?)

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 映射对象表示符
?

Java语言按内存地址区分不同的对象 ==和equal()方法。

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 映射对象表示符
?

Hibernate中用对象表示符(OID)来区分对象 OID是关系数据库中的主键在java对象模型中的等价 物。在运行时,hibernate根据OID来维持java对象和 数据库记录的对应关系。
Customer c1 = (Customer)session.load(Customer.class,new Long(1)); Customer c2 = (Customer)session.load(Customer.class,new Long(1)); Customer c3 = (Customer)session.load(Customer.class,new Long(3)); c1 == c2 ? c1 == c3 ? <id name=“id” type=“long” column=“ID”> <generator class=“increment” /> </id> <generator>子元素用来设定表示符生成器。Hibernate提供了表识符生成器接 口:net.sf.hibernate.id.IdentifierGenerator,并提供了多种内置的实现。

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 映射对象表示符
表示符生成器 increment identity sequence hilo 描述 适用于代理主键。由hibernate自动以递增的方式生成表识符,每次增量为 1 适用于代理主键。由底层数据库生成表识符。条件是数据库支持自动增长数 据类型。 适用于代理主键。Hibernate根据底层数据库序列生成标识符。条件是数据 库支持序列。 适用于代理主键。Hibernate根据hign/low算法生成标识符。Hibernate 把特定表的字段作为“hign‖值。默认情况下,采用 hibernate_unique_key表的next_hi字段。

native
uuid.hex

适用于代理主键。根据底层数据库对自动生成表示符的能力来选择identity、 sequence、hilo
适用于代理主键。Hibernate采用128位的UUID算法来生成标识符。该算法 能够在网络环境中生成唯一的字符串标识符,这种策略并不流行,因为字符 串类型的主键比整数类型的主键占用更多的数据库空间。

assigned

适用于自然主键。由java程序负责生成标识符。不能把setID()方法声明为 Private的。尽量避免使用自然主键。
北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 映射对象表示符
?

Hibernate内置标识符用法

? increment

select max(id) from table; <id name=“id” type=“long” column=“ID”> <generator class=“increment”/> </id> 适用范围: 1。由于不依赖与底层数据库,适合所有的数据库系统。 2。单个进程访问同一个数据库的场合,集群环境下不推荐适用。 3。OID必须为long、int或short类型,如果把OID定义为byte类型,抛异常。

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 映射对象表示符
?

Hibernate内置标识符用法

? Identity

由底层数据库生成标识符.需要把字段定义成自 增型。 my sql 中为auto_increment ms sql server中为identity <generator class=“identity” />

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 映射对象表示符
?

Hibernate内置标识符用法

? sequence

<id name=“id” type=“long” column=“ID”> <generator class=“sequence”> <param name=“sequence”>tester_id_seq</param> </generator> </id>
适用范围: 地层数据库要支持序列。Oracle DB2 SAP等。 OID必须为long、int或shot类型。

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 映射对象表示符
?

Hibernate内置标识符用法

? hilo

<id name=“id” type=“long” clomn=“ID”> <generator class=“hilo”> <param name=“table”>hi_value</param> <param name=“column”>next_value</param> <param name=“max_lo”>100</param> </generator> </id> 使用范围: 该机制不依赖于地层数据库,因此适用于所有的数据库系统。 OID必须为long、int、short类型,如果为byte类型的话,会抛出异常。 Net.sf.hibernate.id.IdentifierGeneratorException:this id generator generates Long、integer、short。

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 映射对象表示符
?

Hibernate内置标识符用法

?

native
<id name=“id” type=“native” column=“ID”> <generator class=“native” /> </id>

适用范围: 该类型能根据地层数据库系统的类型,自动选择合适的标识符生成器,因此很适合于跨数据 库的平台,即在同一个应用中需要连接多种数据库系统的场合。 OID与以上类同。

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 映射对象表示符
?

映射自然主键

?

映射单个自然主键
<id name=“id” column=“NAME” type=“string”> <generator class=“assigned” /> </id> <version name=“version” column=“VERSION” unsaved-value=“0” />

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 映射对象表示符
?

映射自然主键

?

映射复合主键
<composite-id> <key-property name=“name” column=“NAME” type=“string”> <key-property name=“companyId” column=“COMPANY_ID” type=“long”> </composite-id> <version name=“version” column=“VERSION” unsaved-value=“0” /> 使用联合主键的持久化类需要实现serializable接口和覆盖equals()、hashCode()方法。

可以使用customId属性来设置连联合主键 <composite-id name=“costomerid” class=“mypack.CustomerId”> <key-property name=“name” column=“NAME” type=“string”> <key-property name=“companyId” column=“COMPANY_ID” type=“long”> </composite-id> 北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 映射一对多关联关系

Order到Customer的多对一单向关联

Customer 到Order的一对多单向关联

Customer 到Order的一对多双向关联 北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 映射一对多关联关系
?

建立多对一的单向关联关系

<many-to-one name=“customer” column=“CUSTOMER_ID” class=“..Customer” not-null=“true”>
北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 映射一对多关联关系
?

建立多对一的单向关联关系(续)
many-to-one属性: name:设定待映射的持久化类的名字。 column:设定和持久化类的属性对应的表的外键。 class:设定持久化类的属性的类型。 not-null:是否允许为空。

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 映射一对多关联关系
tx = session.beginTransaction(); Customer c = new Customer(); c.setName("TOM"); session.save(c); Order o1 = new Order(); o1.setOrderNumber("1"); o1.setCustomer(c); Order o2 = new Order(); o2.setOrderNumber("1"); o2.setCustomer(c); session.save(o1); session.save(o2); tx.commit();

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 映射一对多关联关系
?

建立多对一的单向关联关系

?

<many-to-one>
tx = session.beginTransaction(); Customer c = new Customer(); c.setName("TOM"); //session.save(c); ?会有什么后果 Order o1 = new Order(); o1.setOrderNumber("1"); o1.setCustomer(c); Order o2 = new Order(); o2.setOrderNumber("1"); o2.setCustomer(c); session.save(o1); session.save(o2); tx.commit(); 北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 映射一对多关联关系
?

建立多对一的单向关联关系

?

级联保存和更新 当hibernate持久化一个临时对象时,在默认情况下,他不会 自动持久化所关联的其他临时对象,会抛出 TransientObjectException.如果设定many-to-one元素的 cascade属性为save-update的话,可实现自动持久化所关联 的对象。
<many-to-one name=“customer” column=“CUSTOMER_ID” class=“..Customer” cascade=“save-update” not-null=“true” /> <property name=“***”> ?

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 映射一对多关联关系
?

映射一对多双向关联关系
Class Customer{ … public Set orders = new Set(); public Set getOrders(){ return orders; } public void setOrders(Set orders){ this.orders = orders; } … <set name=“orders” cascade=“save-update”> <key column=“CUSTOMER_ID” /> <one-to-many class=“..Order” /> </set>

}

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 映射一对多关联关系
?

映射一对多双向关联关系(续)
Hibernate要求在持久化类中定义集合属性时,必须把属性 声明为接口类型,如Set、Map、List.声明为接口类型可提 高持久化类的透明性,当hibernate调用setOrders()方法时, 传递的参数是Hibernate自定义的实现该接口类的实例。如 果定义成类(如HashSet)型,强迫hibernate把该类型的实 例传给他。 通常在定义集合属性时,直接初始化为一个实现类的实例。 private Set orders = new HashSet(); 可避免空指针异常。

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 映射一对多关联关系
?

映射一对多双向关联关系(续)
<set name=―orders‖ cascade=―save-update‖> <key column=―CUSTOMER_ID‖ /> <one-to-many class=―..Order‖ /> </set> name:设定待映射持久化类的属性名。 cascade:设定级联操作的程度。 key子属性:设定与所关联的持久化类对应的标 的外键。 one-to-many子属性:设定所关联的持久化类。

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 映射一对多关联关系
?

映射一对多双向关联关系

? <set>元素的inverse属性

Customer c = (Customer)session .load(Customer.class,new Long(2)); Order o = (Order)session.load(Order.class,new Long(2)); o.setCustomer(c); c.getOrders().add(o); tx.commit(); ------------------------------------------------------Update orders set …... Update orders set …… hibernate执行两条更新语句。

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 映射一对多关联关系
?

映射一对多双向关联关系

? <set>元素的inverse属性(续)

Hibernate会自动清理缓存中的所有持久化对象,按照持久化对象的改变 来同步更新数据库,因此执行了上述的两条更新语句。 重复执行多余的sql语句会影响java性能,解决这一问题的办法是把<set> 元素的inverse属性设为true,该属性的默认值是false。 <set name=―orders‖ cascade=―save-update‖ inverse=―true‖> <key column=―CUSTOMER_ID‖ /> <one-to-many class=―mypack.Order‖ /> </set> Customer和order的双向关联中,customer端的关联只是order端关联 的镜像。当hibernate同时探测到持久化对象customer和order的状态均 发生变化时,仅按照order对象状态更新数据库。
北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 映射一对多关联关系
?

映射一对多双向关联关系

? <set>元素的inverse属性(续)

Customer c = (Customer)session.load(…)); Order o = (Order)session.load(…); o.setCustomer(c); //c.getOrders().add(c); tx.commit(); -----------------------------------------------------以上代码仅设置了order对象的customer属性,hibernate仍然会按照 order对象的状态 的变化来同步更新数据库,执行以下sql语句: Update orders set order_number=?…‘,customer_id=2 where id = 2
北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 映射一对多关联关系
?

映射一对多双向关联关系

? <set>元素的inverse属性(续)

Customer c = (Customer)session.load(……); Order o = (Order)session.load(……); //o.setCustomer(c); c.getOrders().add(c); tx.commit(); ----------------------------------------------------以上代码仅设置了customer对象的orders属性,由于<set>元素的 inverse属性为true,因此,hibernate不会按照customer对象的状态 变化来同步更新数据库。

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 映射一对多关联关系
?

映射一对多双向关联关系

?

<set>元素的invers属性
结论: 1.在映射一对多的双向关联关系时,应该在one方把inverse 属性设为true,这可以提高性能。 2.在建立两个对象的关联时,应该同时修改关联两端的相应 属性: Customer.getOrders().add(order); Order.setCustomer(customer); 这样才会使程序更加健壮,提高业务逻辑层的独立性,使业务 逻辑层的程序代码不受Hibernate实现类的影响。同理,当删 除双向关联的关系时,也应该修改关联两端的对象的相应属性: Customer.getOrders().remove(order); Order.setCustomer(null);
北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 映射一对多关联关系
?

映射一对多双向关联关系

?

级联删除

Customer customer = (Customer) s.load(Customer.class,new Long(2)); Session.delete(customer); tx.commit(); ----------------------------------------------------------------如果cascade属性取默认值none,不会自动删除和customer关联的其他持久化对象。如 果希望删除customer时,自动删除和customer关联的order对象,可把cascade属性设 为delete。 <set name=―orders‖ cascade=―delete‖ inverse=―true‖> <key column=―CUSTOMER_ID‖ /> <one-to-many class=―mypack.Order‖ /> </set> 再运行删除方法的时候,会自动删除order对象,此时hibernate执行如下语句: Delete from customer where customer_id = 1; Delete customer where id = 1;

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 映射一对多关联关系
?

映射一对多双向关联关系

?

父子关系

Customer customer = (Customer)session.load(……); Order order = (Order)customer.getOrders().iterator().next(); //删除关联关系 customer.getOrders().remove(order); order.setCustomer(null); tx.commit(); -------------------------------------------------------------如果cascade为默认值none,hibernate会执行如下语句: Update orders set Customer_id = null where ID = 2; 如果希望程序自动删除不再和customer关联的order对象,可以把cascade属性设为 all-delete-orphan。 <set name=―orders‖ cacade=―add-delete-orphan‖ inverse=―true‖> <key column=―CUSTOMER_ID‖ /> <one-to-many class=―mypack.Order‖ /> </set> Delete from orders where CUSTOMER_ID = 2 and ID = 2 北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 映射一对多关联关系
?

映射一对多双向关联关系

?

父子关系
当customer.hbm.xml的<set>元素的cascade属性取值为 all-delete-orphan,Hibernate会按照如下方式处理customer对象: 1.当保存或更新customer对象时,级联保存或更新所有关联的order 对象,相当于save-update. 2.当删除customer对象时,级联删除所有的order对象,相当于delete。 3.删除不再和customer对象关联的所有order对象。 当关联双方存在父子关系时,就可以把父方的cascade属性设为 all-delete-orphan. 所谓父子关系:是指父方来控制子方的持久化生命周期,子方对象必 须和一个父方对象关联。

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 映射一对一关联关系
?

映射一对一关联

?

按照外键映射
ADDRESSS表 --------------ID<<PK>> CITY STREET PROVINCE

CUSTOMERS表 --------------ID<<PK>> NAME HOME_ADDRESS<<FK>>

customer.hbm.xml: <many-to-one name=“homeAddress” class=“mypack.Address” column=“HOME_ADDRESS” cascade=“all” unique=“true” /> address.hbm.xml <one-to-one name=“customer” class=“mypack.Customer” property-ref=“homeAddress” /> one-to-one元素的property-ref属性为homeAddress,表明建立了从homeAddress对象到 Cusotmer对象的关联.

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 映射一对一关联关系
映射一对一关联(主键映射)
CUSTOMERS表 --------------ID<PK> NAME ADDRESSS表 --------------ID<PK><FK> CITY STREET PROVINCE

customer.hbm.xml: <one-to-one name=“address” class=“mypack.Address” cascade=“all” /> address.hbm.xml <one-to-one name=“customer” class=“mypack.Customer” constraint=“true” /> one-to-one元素的constraint属性为true,表明Address表的ID主键同时作为外键参照 Customers表。在address.hbm.xml文件中,必须为OID使用foreign标识符生成策略。 <id name=“id” type=“long” column=“ID”> <generator class=“foreign”> <param name=“property”>customer</param> </generator> </id> 北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 映射多对多关联关系
?

映射单向多对多关联
LINKS表 ---------------TID<PK><FK> SID<FK><PK> STUDENTS表 ---------------ID<PK> STUNO

TEACHERS表 ---------------ID<PK> NAME

Teacher.hbm.xml <set name=―students‖ table=―links‖ lazy=―true‖ inverse=“true”> <key column=―tid‖ /> <many-to-many class=―Student‖ column=―sid‖ /> </set> Student.hbm.xml <set name=―teachers‖ table=―links‖ lazy=―true‖> <key column=―sid‖ /> <many-to-many class=―Teacher‖ column=―tid‖ /> </set>

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 操纵持久化对象
Session接口提供增、删、改、查功能。 Session中有一个缓存,位于缓存中对象处 于持久化状态,他和数据库中的记录相对 应。Session能够在某些时间点,按照缓存 中的持久化对象的属性变化来同步更新数据 库,这一过程被称为清理缓存。除了持久化 状态还有游离态和临时态。
北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 操纵持久化对象
?

Java对象在JVM中的生命周期
Customer c = new Customer(“TOM”,new HashSet()); Order o1 = new Order(“Tom_order001”,null); Order o2 = new Order(“Tom_order002”,null); o1.setCustomer(c); c.getOrders().add(o1); o1 = null; o2 = null; c = null;

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 操纵持久化对象
?

理解session的缓存 当session的save()方法持久化一个对象 时,该对象被载入缓存,以后即使程序中 不再引用该对象,只要缓存不清空,该对 象仍然处于生命周期中。当试图load()对 象时,会判断缓存中是否存在该对象,有 则返回。
北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 操纵持久化对象
?

理解session的缓存(续)
Customer c = new Customer(“TOM”,new HashSet()); session.save(c); Long id = c.getId(); c = null; Customer c2 = (Customer)session.load(Customer.class,id); tx.commit(); session.close(); c2.getName(); C2 = null; --------------------------------------------------------------------------------------------缓存的作用: 1。减少访问数据库的频率。 2。保证缓存中的对象与数据库中的相关记录保持同步。 3。当缓存中的持久化对象之间存在循环关联关系时,Session会保证不出现访问对象图的死循 还,以及由死循环引起的JVM堆栈溢出异常。 提示: 当session加载了customer对象后,会为customer对象的值类型的属性复制一份快照。当清理 缓存时,通过比较对象的当前属性和快照,来判断对象的那些属性发生了变化。 北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 操纵持久化对象
?

理解session的缓存
Session在清理缓存时,按照以下顺序执行sql语句。 1。按照应用程序调用save()方法的先后顺序,执行所有的对实体进行插入的insert语句。 2。所有对实体进行更新的update语句。 3。所有对实体进行删除的delete语句。 4。所有对集合元素进行删除、更新或插入的sql语句。 5。执行所有对集合进行插入的insert语句。 6。按照应用程序调用delete()方法的先后执行。 默认情况下: 1。当应用程序commit()方法的时候,先清理缓存,然后在向数据库提交事务。 2。当调用find()或iterator()时,如果对象属性发生变化,会先清理缓存,以保证查询结果 能够反映持久化对象的最新状态。 3。显式调用flush()。 --------------------------------------------------------------------------------------------提示: Commit()和flush()方法的区别: Flush进行清理缓存的操作,执行一些列sql语句,但不提交事务;commit方法先调用flush方 法,然后提交事务。提交事务意味着对数据库操作永久保存下来。 北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 操纵持久化对象
?

理解session的缓存 session.setFlushMode(FlushMode.AUTO);
清理缓存的模式 Session的 查询方法 tx的 commit() Session的 flush()

FlushMode.AUTO
FlushMode.COMM IT FLushMode.NEVE R

清理
不清理 不清理

清理
清理 不清理

清理
清理 清理

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 操纵持久化对象
?

在hibernate中java对象的状态
临时状态(transient):刚刚用new语句创建,没有被持久化,不处于session中。该对象 成为临时对象 持久化状态(persistent):已经被持久化,加入到session的缓存中。该状态的对象为持久 化对象。 游离状态(detached):已经被持久化,但不处于session中。该状态的对象为游离对象。

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 操纵持久化对象
程序代码
tx = session.beginTransaction(); Customer c = new Customer); Session.save(c)

生命周期
开始生命周期

状态
临时状态

处于生命周期中

转变为持久化状态

Long id=c.getId(); c = null; Customer c2 = (Customer)session.load(Customer.class,id); tx.commit();
session.close(); c2.getName(); c2 = null;

处于生命周期中

处于持久化状态

处于生命周期中 处于生命周期中 结束生命周期

转变为游离态 处于游离态 结束生命周期

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 操纵持久化对象
?

在hibernate中java对象的状态

?

临时对象特征 不处于session中,不被任何session关联。 数据库中没有对应的记录。 以下情况,对象进入临时状态: 1.new 语句刚创建了一个对象。 2.session的delete方法使持久化对象或游离 对象转变为临时对象,对于游离对象,该方法从数 据库中删除记录,对于持久化对象,该方法从数据 库中删除记录,还要删除缓存中的对象。

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 操纵持久化对象
?

在hibernate中java对象的状态

?

持久化对象特征 1.位于一个session缓存中,总是被一个 session关联。 2.持久化对象和数据库记录相对应。 3.清理缓存时,会根据对象属性变化,同步 更新数据库。 4.save把临时对象转变为持久化对象。 5.load或find或get返回的对象总是持久化状态。 6.find方法返回的list存放的都是持久化对象。 7.update、save、SaveOrUpdate和Lock方法使游离对象装变 为持久化对象。 在实际的应用程序中应该避免一个java对象被多个session实例关 联,会导致重复执行sql语句,并且极容易出现一些并发问题。
北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 操纵持久化对象
?

在hibernate中java对象的状态

? 游离对象特征

1.不再位于session的缓存中,游离对象不被 session关联。 2.游离对象由持久化转变过来的,因此在数据 库中可能还存在与它对应的记录(前提条 件是没有其他程序删除了这条记录)。

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 操纵持久化对象
?

在hibernate中java对象的状态

?

游离对象特征 在以下情况下,持久化对象转变为游离对象: 1.close方法使缓存被清空,缓存中的所有的 对象都变为游离对象。如果没有引用他们 的话,他们就会结束生命周期。 2.evict方法从缓存中删除一个持久化对象, 使他变为游离态对象。当缓存中保存了大量的持久 化对象时,会消耗许多内存空间,使用该方法删掉 一些对象来节省空间。

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 操纵持久化对象
?

Session的增、删、改、查方法

? save:

1.对象加入缓存,成为持久化对象。 2.<id name=“id” cloumn=“ID” type=“long”> <generator class=“increment”> </id>
北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 操纵持久化对象
?

Session的增、删、改、查方法

? update:

将游离对象转变为持久化对象。不论对象属性 是否发生变化,该方法都会执行update操作。 如果希望仅当属性变化时才执行update语句的 话可进行如下配置: <class name=“…” table=“…” select-before-update=“true”>
北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 操纵持久化对象
?

Session的增、删、改、查方法

? saveOrUpdate:

该方法同时包含save和update方法,如果参数是临时对象 就用save方法,如果是游离对象就用update方法,如果是 持久化对象就直接返回。
临时对象判断法: 1。OID为null 2。具有version属性并取值为null 3。在映射文件中为<id>元素设置了unsaved-value属性,并且OID属性取值与属 性匹配。 4。在映射文件中为<version>元素设置了unsaved-value属性,并且version属性取 值与属性匹配。 5。自定义了Interceptor实现类,并且isUnsaved方法返回Boolean.true 如果id的类型为long,则默认值为0,此时需要在配置文件中设置id的unsaved-value 为0。

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 操纵持久化对象
?

Session的增、删、改、查方法 ?load和get: 从数据库加载指定的OID持久化对象。 如果数据库中不存在该记录时,load方法会 抛出异常,而get方法返回null。

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 操纵持久化对象
?

Session的增、删、改、查方法

? delete

如果参数是持久化对象,就执行一个delete语句, 若为游离对象,先使游离对象被session关联, 使他变为持久化对象,然后计划执行一个 delete语句。

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 操纵持久化对象
?

Session的增、删、改、查方法
cascade属性值 none save-update delete all 描述 忽略关联对象,默认值 保存或更新当前对象时,级联保存关联 的临时对象,更新关联的游离对象。 删除对象时,级联删除关联的对象。 包含save-update和delete的行为。

delete-orphan
all-delete-orphan

删除所有和当前对象解除关联关系的对 象。
包含all和delete-orphan的行为。
北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 操纵持久化对象
?

与触发器协同工作
Session.save(c); Session.flush(); Session.refresh(c); -----------------------------------------------------触发器的行为导致缓存与数据库中的数据不一致。解决办法是执行完 操作后,立即调用session的flush方法和refresh方法,迫使缓存与 数据库同步。 Session的update操作方法盲目的激活触发器 如果游离状态的对象的属性和数据库一致,则更新操作是多余的。 为避免这种情况: <class name=―‖ table=―‖ select-before-update=―true‖> …… </class>
北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 映射组成关系

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 映射组成关系
Class customer{ …… Address homeAddress ; Address comAddress ; …… } Table customers{ …… home_province home_city home_street com_province com_city com_street …… }

<compont name=“homeaddress” class=“mypack.Address”> <parent name=“customer” /> <property name=“street” type=“string” column=“HOME_STREET” /> <property name=“city” type = “string” cloumn=“HOME_CITY” /> <property name=“street” type = “string” cloumn=“HOME_STREET” /> </component> <compont name=“comaddress” class=“mypack.Address”> <parent name=“customer” /> <property name=“street” type=“string” column=“COM_STREET” /> <property name=“city” type = “string” cloumn=“COM_CITY” /> <property name=“street” type = “string” cloumn=“COM_STREET” /> </component> 北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 映射组成关系
?

映射组成关系

? 区分值和实体
持久化类的属性分为两种:值(value)类型和实 体类型(entity)类型。值类型没有OID,不能被 单独持久化,他的生命周期依赖于所属的持久 化类的对象的生命周期,组件类型就是一种值 类型;实体类型有OID,可单独持久化。

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 映射组成关系
?

映射组成关系

?

访问由组成关系的持久化类

1.Conf.addClass(Customer.class).addClass(Address.class); 抛映射异常,原因是Address.hbm.xml文件没找到。 2. Customer c = new Customer(); c.setHomeAddress(new Address()); c.setComAddress(new Address()); …… Session.save(c); ---------------------------------------------------Session.save(new Address()); 映射异常:unkown entity class.

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 映射组成关系
?

映射复合组成关系

Computer类和他的组件类 北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 映射组成关系
?

映射复合组成关系

<component name="cpuBox" class="mypack.CpuBox"> <parent name="computer" /> <property name="type" type="string" column ="CPUBOX_TYPE" /> <component name="graphicsCard" class="mypack.GraphicsCard"> <parent name="cpuBox" /> <property name="type" type="string" column ="GRAPHICSCARD_TYPE" /> </component> <many-to-one name="vendor" column="CPUBOX_VENDOR_ID" class="mypack.Vendor" not-null="true" /> </component>

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate映射类型
?

内置映射类型
Hibernate integer int long short byte float double big_decimal character java int Integer long Long short Short byte Byte float Float double Double java.math.BigD ecinimal char Character String sql INTEGER BIGINT SMALLINT TINYINT FLOAT DOUBLE NUMERIC CHAR(1) 取值范围 4 8 2 1 4 8 8位含2位小数部分 定长字符

string
boolean yes_no true_false

String
boolean Boolean boolean Boolean

VARCHAR
BIT CHAR(1)

变长串
布尔 布尔 布尔

boolean CHAR(1) 北京传智播客教育 www.itcast.cn Boolean

—高级软件人才实作培训专家! Hibernate映射类型
?

java时间和日期类性
java util.Date sql.Date sql DATE 取值范围 YYYY-MM-DD

Hibernate date

time
timestamp calendar calendar_date

util.Date sql.Time
util.Date sql.timestamp java.util.Calendar java.util.Calendar

TIME
TIMESTAMP TIMESTAMP DATE

HH:MM:SS
YYYYMMDDHHMMSS YYYYMMDDHHMMSS YYYY-MM-DD

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate映射类型
?

大对象类型的映射
java byte[] String 实现类 sql.Clob sql.Blob sql VARBINARY(BLOB) CLOB BARBINARY(BLOB) CLOB BLOB

Hibernate binary text serializable clob blob

不允许以上类型来定义OID

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate映射类型
?

大对象类型的映射
如果持久化类的字段为blob或clob类型,保存时需要包含两步: ------------------------------------------------Customer c = new Customer(); //现保存一个空的clob实例 c.setDescription(Hibernate.createClob()); session.save(c); session.flush(); //锁定记录 session.refresh(customer,LockMode.UPGRADE); oracle.sql.CLOB clob = c.getDescription(); //写入大文本 java.io.Writer pw = clob.getCharacterOutputStream(); pw.write(longtext); pw.close(); tx.commit(); session.close();

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate映射类型
?

JDK自带的个别java类的映射类型
Hibernate class locale java java.lang.Class java.util.Locale sql VARCHAR VARCHAR

timezone
currency

java.util.TimeZone
java.util.Currency

VARCHAR
VARCHAR

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate的检索策略
?

hibernate的检索策略简介
检索策略的作 用域 类级别 可选的检索策略 立即 延迟 默认的检索策略 延迟 运行时行为受影响的 session的检索方法 load

关联级别

立即 延迟 迫切左外连接检索

延迟

load get

延迟

类级别和关联级别可选的检索策略及默认的检索策略
北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate的检索策略
?

hibernate的检索策略简介(续)
类级别 关联接别

检索策略的类型

立即

立即加载检索方法制定的对象

立即加载关联的对象、可设定批量检索数 量 延迟加载与检索方法指定的对象关联对象。 可设定批量检索数量。 通过左外连接加载与检索方法指定的对象 关联的对象。

延迟检索

延迟加载检索方法指定的对象

迫切左外

不适用

三种检索策略的运行机制

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate的检索策略
?
属性 lazy

hibernate的检索策略简介(续)
可选值 true false auto true false 默认值 false 描述 如果为true,延迟加载, class和set有此属性 如果为true,适用迫切左 外连接检索。在 <many-to-one>和 <one-to-one> <set>中存在。 合理取值3~10之间, class和set存在。

fetch

<many-to-one>和<one-to-one>中为auto, 在<set>元素中为false。

batch-size

正整数

1

映射文件中用于设定检索策略的几个属性

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate的检索策略
?

类级别的检索策略

? 立即

<class ...... lazy=“false”> ? 延迟检索 <class ...... lazy=“true”> if(!Hibernate.isInitialized(c)){ Hibernate.initialize(c); }
北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate的检索策略
?

一对多和多对多关联的检索策略(set)

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate的检索策略
?

一对多和多对多关联的检索策略

? 立即检索 ? 延迟检索 ? 批量延迟检索 ? 批量立即检索 ? 迫切左外连接检索

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate的检索策略
?

多对一和一对一的检索策略

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate的检索策略
?
检索策略 立即检索

比较三种检索策略
优点 对应用程序完全透明,不管对象处 于持久化状态还是游离状态,应用 程序都可以从一个对象导航到关联 的对象 由应用程序决定需要加载哪些对象, 可以避免执行多余的select语句,以 及避免加载应用程序不需要访问的 对象。因此能提高检索性能,并节 省内存空间。 (1)对应用程序完全透明,不管对象 处于持久化状态还是游离状态,都 可从一个对象导航到另一个对象。 (2)使用了外连接,select语句少 缺点 (1)select语句多 (2)可能会加载应用程序不需 要访问的对象,浪费许多内 存空间。 应用程序如果希望访问游离 状态的代理类实例,必须保 证她在持久化状态时已经被 初始化。 (1)可能会加载应用程序不需 要访问的对象,浪费内存。 (2)复杂的数据库表连接也会 影响检索性能。 优先考虑使用的场合 (1)类级别 (2)应用程序需要立即访问 的对象 (3)使用了二级缓存 (1)一对多或者多对多关联 (2)应用程序不需要立即访 问或者根本不会访问的对 象 (1)多对一或一对一关联 (2)需要立即访问的对象 (3)数据库有良好的表连接 性能。

延迟检索

迫切左外 连接检索

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! hibernate检索方式
1。对象导航图 2。OID检索 3。HQL检索 4。QBC检索 5。本地SQL检索

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! hibernate检索方式
?

检索方式简介

?

HQL检索方式

1。在查询语句中设定各种查询条件 2。支持投影,仅检索出对象的部分属性 3。支持分页 4。连接查询 5。分组查询 6。内置聚集函数 7。调用用户自定义的函数 8。嵌入式查询 9。动态绑定参数 Query query = session.createQuery(“from Customer as c where c.name=:custoerNa me and c.age = :customerAge”); query.setString(“customerName”,”Tom”); query.setInteger(“customerAge,21); query.list(); 北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! hibernate检索方式
?

检索方式简介

?

QBC检索方式
主要由Criteria、Criterion接口和Expression类组成,他支持在运行时动态生成查询语句。 -----------------------------------------------------------------------------------------Criteria criteria = session.createCriteria(Customer.class); Criteria c1 = Expression.like(“name”,”T%”); Criteria c2 = Expression.eq(“age”,new Integer(21)); criteria.add(c1) criteria.add(c2); criteria.list(); -----------------------------------------------------------------------------------------方法链编程: session.createCriteria(Customer.class).add(Expression.like(“name”,”%T”)) .add(Expression.eq(“age”,new Integer(21))) .list();

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! hibernate检索方式
?

检索方式简介

?

SQL检索方式
Query query = session.createSQLQuery(“select {c.*} from CUSTOMERS c where c.NAME like :customerName and c.AGE=:customerAge”,”c”, Customer.class); //动态绑定参数 query.setString(“customerName”,”T%”); query.setInteger(“customerAge”,new Integer()21); //执行sql select语句,返回查询结果。 List list = query.list();

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! hibernate检索方式
?

检索方式简介

? 使用别名

from Customer as c where c.name = :customerName as 可省略。

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! hibernate检索方式
?

检索方式简介

? 多态查询

session.createQuery(“from Employee”); 查询出所有的实体 from java.lang.serializable(支持接口) from java.lang.Object

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! hibernate检索方式
?

检索方式简介
对查询结果排序
hql 查询: session.createQuery(―from Employee c order by c.name”); qbc查询: session.createCriteria(Customer.class).addOrder(Order.asc(―name‖));

分页查询
hql 查询: session.createQuery(―from Employee c order by c.name”).setFirstResult(97) .setMaxResults(10); qbc查询: session.createCriteria(Customer.class) .aaddOrder(Order.asc(―name‖)) .setFirstResult(97).setMaxResult(10).list(); 北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! hibernate检索方式
?

检索方式简介
检索单个对象(要确保查询结果有且只有一条记录)

hql 查询: session.createQuery(―from Employee c order by c.name”) .setMaxResults(1).uniqueResult(); qbc查询: session.createCriteria(Customer.class) .addOrder(Order.asc(―name‖)) .setMaxResult(1).uniqueResult();

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! hibernate检索方式
?

检索方式简介

? 绑定参数

hql 查询: session.createQuery(―from Employee c where c.name = :customerName”); query.setString(―customeName‖,‖Tom‖); ---------------------------------------------------............................c.name=? query.setString(0,‖Tom‖);

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! hibernate检索方式
?

检索方式简介

? 在影射文件中定义命名查询语句

<class> ....... </class> <query name=―findCustomersByName‖> <![CDATA[from Cusomter c where c.name like:name]]> </query> -----------------------------------------------------------------query = session.getNamedQuery(―findCustomersByName‖); query.setString(―name‖,‖Tom‖); query.list();

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! hibernate检索方式
?

设定查询条件
运算类型 HQL运算符 = <> >= 比较运算 < <= is null is not null QBC运算方法 Express.eq() Express.not(Express.eq()) Express.ge() Express.lt() Express.le() Express.isNull() Express.isNotNull() 含义

范围运算符

in
not in between not between

Express.in()
Express.not(Express.in()) Express.between() Express.not(Express.between()) 北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! hibernate检索方式
?

设定查询条件(续)
运算类型 字符串模式 匹配 逻辑 HQL运算符 like and or not QBC运算方法 Expression.like() Expression.and()| Expression.conjunction() Expression.or()| Expression.disjunction() Expression.not() 含义

北京传智播客教育 www.itcast.cn

hibernate检索方式
?

连接查询
程序中指定的连接查询类型 内连接 迫切内连接 隐式内连接 左外连接 迫切左外连接 右外连接 交叉连接 left out join out join left out join fetch out join fetch right out join | out join ClassA,ClassB HQL语法 inner join | join inner join fetch | join fetch QBC语法 Criteria.cre ateAlias() 不支持 不支持 不支持 FetchMode. EAGER 不支持 不支持 适用于不存在 关联关系的持 久化类 适用范围

适用于由关联 关系的持久化 类

—高级软件人才实作培训专家! hibernate检索方式
?

连接查询

? 迫切左外连接
HQL: createQuery(―from Customer c left join fetch c.orders o where c.name like ?T%‘‖); QBC: createCriteria(Customer.class) .setFetchMode(―orders‖,FetchMode.EAGER) .add(Expression.like(―name‖,‖T‖,MatchMode.START))

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! hibernate检索方式
?

连接查询

? 左外连接
HQL: createQuery(―from Customer c left join c.orders o where c.name like ?T%‘‖);

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! hibernate检索方式
?

连接查询

? 内连接

HQL: createQuery(―from Customer c inner join c.orders o where c.name like ?T%‘‖); HQL: createQuery(―from Customer c join c.orders o where c.name like ?T%‘‖); QBC: createCriteria(Customer.class). .add(Expression.like(―name‖,‖T‖,MatchMode.START)) .createCriteria(―orders‖) .add(Expression.like(―orderNumber‖,‖T‖,MatchMode.START));

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! hibernate检索方式
?

连接查询

? 迫切内连接

HQL: createQuery(―from Customer c inner join fetch c.orders o where c.name like ?T%‘‖); QBC: createCriteria(Customer.class). .setFetchMode(―orders‖,FetchMode.EAGER) .createAlias(―orders‖,‖o‖) .add(Expression.like(―this.name‖,‖T‖,MatchMode.START)) .add(Expression.like(―o.orderNumber‖,‖T‖,MatchMode.START))

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! hibernate检索方式
?

连接查询

? 隐式内连接
HQL: createQuery(―from Order o where o.customer.name like ?T%‘―); 等价于: from Order o join o.customer c where c.name like ?T%‘ QBC: 不支持

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! hibernate检索方式
?

连接查询

? 右外连接
HQL: from Customer c right outer join c.orders o where o.name like ?T%‘ 等价于: from Customer c right join c.orders o where o.name like ?T%‘

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! hibernate检索方式
?

连接查询

? 使用SQL风格的交叉连接和隐式内连接
HQL: 交叉连接查询:from Customer,Order 标准SQL风格的内连接:from Customer c inner join c.orders SQL风格的隐式内连接查询:from Customer c,Order o where c.id = o.customer_id

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! hibernate检索方式
?

连接查询

?

关联级别运行时的检索策略 1.若在HQL、QBC代码中没有显式指定检索策 略,使用映射文件中的检索策略。但HQL总是忽略 映射文件中设置的迫切左外连接检索策略。 2.若代码中显示指定了检索策略,则覆盖映射文件中 的检索策略。 3.目前的hibernate版本只允许在一个查询语句中迫切 左外连接检索一个集合。 4.HQL支持各种各样的连接查询。

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! hibernate检索方式
?

报表查询

?

投影查询 指查询结果仅包括部分实体或实体的部分属 性。通过select来实现。

from Customer c join c.orders o where o.orderNumber like ?T%? 如果希望查询结果中只包含Customer对象,可使用以下形式: select c from Customer c join c.orders o where o.orderNumber like T%? session.createQuery(“select c.id,c.name,o.orderNumber from Customer c join c.orders o where o.orderNumber like ?T%?”) ----------------------------------------------------------------------------------对应的sql语句为: select c.ID,c.NAME,o.ORDER_NUMBER from CUSTOMERS c inner join ORDERS o on c.ID-=o.CUSTOMER_ID where o.ORDER_NUMBER like?T%? -----------------------------------------------------------------------------------过滤重复元素 createQuery(“select distinct c.name from customer c”); 北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! hibernate检索方式
?

报表查询

?

使用聚集函数 createQuery(“select count(*) from Customer c”).uniqueResult();

createQuery(“select avg(c.age) from Customer c”).uniqueResult(); createQuery(“select max(c.age),min(c.age) from Customer c”).uniqueResult(); 分组查询: createQuery(“select c.name,count(c) from Customer group by c.name”);

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! hibernate检索方式
?

高级查询技巧
动态查询: session.createCriteria(Customer.class) .add(Expression.like(―name‖,name.toLowerCase()),MatchMode.ANYWHERE) .add(Expression.eq(―age‖,new Integer(11))); 集合过滤: hql: createQuery(―from Order o where o.customer=:customer and o.price>100 order by o.price‖).setEntity(―customer‖,customer).list(); 使用集合过滤: session.createFilter(customer.getOrders(),‖where this.price > 100 order by this.price‖).list(); 子查询: from Customer c where 1 < (select count(o) from c.orders o); 本地SQL查询: String sql=―select cs.ID as {c.id},cs.NAME as {c.name},cs.AGE as {c.age} from CUSTOMERS cs where cs.ID = 1‖; Query query = session.createSQLQuery(sql,‖c‖,Customer.class); 第二个参数是类的别名,在SQL语句中,每个字段的别名必须位于打括号内。 北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! hibernate检索方式
?

查询性能优化

? iterate方法

query1=session.createQuery(―from Customer c‖); List result1 = query1.list();

Query query2 = session.createQuery(―from Customer c where c.age < 30‖); Iterator it = query2.iterator(); query接口的iterate方法首先检索ID字段,然后根据ID字段到一级缓存、二级缓存中查 找,有则返回,否则查库。

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! hibernate检索方式
?

查询性能优化

? 查询缓存

在hibernate.properties中的 hibernate.cache.use_query_cache=true query = session.createQuery(―from Cusotmer c where c.age>:age‖); query.setInteger(―age‖,new Integer(1)); query.setCacheable(true); -----如果想更加细粒度的控制查询缓存,可设置缓存区域 query.setCacheRegion(―customer‖)

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! hibernate检索方式
?

小结
比较方面 可读性 HQL检索 优点:和sql相近,易读 QBC检索 将语句肢解成一组criteria,较差

功能
查询语句形 式 何时被解析 可扩展性 对动态查询 语句的支持

支持各种查询
基于字符串形式的sql 运行时被解析 不具扩展性 支持动态查询,编程麻烦

不支持报表查询和子查询。有限的连接查询
更加面向对象 编译时被解析,更易排错 用户可扩展criteria接口 适合动态生成查询语句

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 影射继承关系
?

整个关系树对应一个表(存在一个表中)

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 影射继承关系
?

每个类对应一个表(三个表,主从关系)

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! 影射继承关系
?

关系树的每个具体类对应一个表

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate数据库级别的并发
理解数据库级别的并发 事务隔离问题-丢失更新:

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate数据库级别的并发
理解数据库级别的并发 事务隔离问题-脏读:

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate数据库级别的并发
理解数据库级别的并发 事务隔离问题-不可重复读:

第二类丢失更新时不可重复读的一种特例.两个事务都更新同一数据,第一个 事务完成后提交,第二个事务完成时也提交.则第一个事务所做的修改被覆盖 了.此种现象为第二类丢失更新.

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate数据库级别的并发
理解数据库级别的并发 事务隔离问题-幻读:

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate数据库级别的并发
理解数据库级别的并发 ANSI 事务隔离级别 ANSI SQL 标准定义了隔离级别,但并不是SQL数据库独有.JTA也定义了同样的隔离级别.级别 越高,成本越高. 1.如果系统允许脏读但不会丢失更新我们称之为read uncommited隔离级别.一个事务不可能向 另外一个事务所控制的行在未提交的情况下写入数据.任何事务都可以读取任何行数据.这一隔离级 别可以通过的DBMS的排他写锁实现. 2.如果系统允许不可重复读但不能脏读我们称之为read commited隔离级别.这可以通过共享读锁和 排他写锁实现.读操作不会阻止其他事务访问行数据.然而一个未提交的写事务会阻止所有访问该行 的事务. 3.既不允许不可重复读也不允许脏读,我们称之为repeatable read.幻读还能够发生.读事务阻止 了写事务(不是其他的读事务).写事务阻止所有的其他事务. 4.Serializable提供了最严格的事务隔离级别.他按照串行化的方式执行事务,不支持并发访问,不能 只通过行级锁实现,必须用其他的一些机制来阻止其他新插入的行.

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate数据库级别的并发
理解数据库级别的并发 选择隔离级别 隔离级别过高损害高并发应用的可扩展性.级别不够也会引起莫名的问题.对于数据库的事务语义 来,Hibernate尽可能的做到透明.然而缓存和乐观锁会影响到这些语义.如何选择合理的隔离级别? 选择标准 1.消除读未提交隔离级别,使用未提交数据非常危险. 2.大多数应用不需要可串行化级别 3.在读已提交和可重复读间选择. 设置事务隔离级别允许为所有的数据库事务选择合理的锁策略.但如何设置? 设置隔离级别 每个数据库连接都有默认的隔离级别,通常是读已提交或可重复读.可以通过数据库配置设置,也可在 应用程序中设置.例如Hibernate: hibernate.connection.isolation = 4 1—Read uncommitted isolation 2—Read committed isolation 4—Repeatable read isolation 8—Serializable isolation 注意:Hibernate不可能改变在受管环境下由应用服务器提供的数据库连接的隔离级别,只能通过改变 应用服务器配置的方式来改变.设置隔离级别是全局选项,会影响所有的连接和事务.有时需要为 某个特定事务指定更多的限制.Hibernate依赖于乐观的并发控制,使用版本检查和 悲观锁实现附加的锁支持.

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate乐观并发控制
乐观并发控制 乐观并发控制只在工作单元结束后产生错误.多用户应用通常会默认采用乐观并发控制以及 与数据库连接采用读已提交的隔离级别.在特定的相应时刻可获得附加的这一隔离级别.比 如要求进行一个可重复的读,这一方案能够确保最佳的性能和扩展性. 理解乐观策略 有三种方案来处理在第二个事务中的丢失更新问题. 1.Last commit wins(后提交成功) 事务都成功,后提交覆盖前一个的改变,没有错误消息. 2.First commit wins(前提交成功) B提交时得到错误消息,要求必须重启会话,刷新数据后对非脏数据再进行操作. 3.Merge conflicting updates(合并冲突更新) A成功提交,B提交时伴随错误消息而终止,B用户可以选择性的应用变更,而不是重复会话中的 所有步骤.如果没有启动乐观并发控制,则运行在1模式下(默认值),结 果是导致没有任何错 误消息而丢失更新.

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate乐观并发控制
理解乐观策略 如果没有启动乐观并发控制(默认不启动),程序运行于后提交成功模式(谁后提交谁有效,不关心数 据),用户可能对这种模式比较沮丧,自己所做的大量工作连个错误消息都没有的情况下丢失了!
很明显,后提交失败模式更吸引人.B提交时会得到错误消息,有其他人先修改数据了.提示用户刷新数 据后,重新启动会话. 第三种模式不显示错误消息而是强制用户后退所有的步骤.我们要提供对话框允许用户手动合并有冲 突的变更.这是一种最佳的方式,因为没有工作丢失,而且由于并发控制的失败用户也很少感觉到沮丧. 然而对于开发者来说提供对话框来合并变要比给出错误消息和重复用户所有工作会更耗时.这要留给 你来决定采用哪个策略.

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate乐观并发控制
乐观并发控制 在Hibernate中启动版本控制 版本与时间戳.该属性不应该由应用程序访问,因此访问级别应设置为field.对于时间戳来说,检索 JVM时间也不够安全,比如在集群环境下,某些节点没进行时间同步.我们需要从数据库所在主机检索 当前时间,这需要通过设置<timestamp source=―db‖>来实现,不是每个方言都支持(查看方言源 码).

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate乐观并发控制
乐观并发控制 版本机制的自动管理 没有版本号或时间戳的版本控制 若没有版本或时间戳字段,Hibernate也能实现版本控制,但仅限同一会话内.若游离对象要实现乐观 锁必须用版本或时间戳.这种版本的实现是通过对数据库的当前状态和最开始查询出来的数据对象进 行对比完成的.设置如下: <class … optimistic-lock="all"> Hibernate会执行如下sql语句: update ITEM set ITEM_PRICE='12.99? where ITEM_ID=123 and ITEM_PRICE='9.99? and ITEM_DESCRIPTION="An Item― and ... and SELLER_ID=45 如果有并发产生的话,会更新0行.结果抛出脏对象异常. 另外,如果设置optimistic-lock=―dirty―,Hibernate只包含修改的属性.同时,还需要设置 dynamic-update=―true‖. 这种方案不推荐使用.

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate额外的隔离保证
获得额外的隔离保证 有几种方式可以避免不可重复并升级到更高的隔离级别. 显式悲观锁 对于某个特定的工作单元需要更好的隔离保证.而不是应该采用一刀切的做法. 比如说,我们在标量查询中会需要可重复读: Item i = (Item) session.get(Item.class, 123); <!– 此期间有其它事务改写描述字段并提交事务 --> String description = session.createQuery("select i.description from Item i" +" where i.id = :itemid").setParameter("itemid", i.getId() ).uniqueResult(); 第二次查询可能返回一个和第一次查询不一致的描述数据,原因是在这两次查询期间有另外一个事务 改写了该item对象在数据库中的对应的description字段的值,而且提交了事务.结果造成了不可 重复读. 也就是如果数据库隔离级别为读已提交的话,则第二次的标量查询可能会读到其他事务提交的数据. 这是典型的不可重复读.(简单但很典型)

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate额外的隔离保证
获得额外的隔离保 相对与把数据库连接切换到更高的可重复读的隔离级别来说,在hibernate中我们可以选择lock方法 来获得更强的隔离保证. Item i=(Item)s.get(Item.class,123); s.lock(i,LockMode.UPGRADE); String d=(String)s.createQuery("select.. 使用了LockMode.UPGRADE之后,可以保证在连续两次查询过程中,没有其他的并发事务可对其进行 修改.上面代码等同于以下代码: session.get(Item.class,123,LockMode.UPGRADE); LockMode.UPDATE会导致执行类似SELECT ... FOR UPDATE的SQL语句(依赖于数据库方言).还 有一种变形(LockMode.UPDATE_NOWAIT)

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate额外的隔离保证
获得额外的隔离保证 Hibernate Lock模式 1.LockMode.NONE: 不要访问数据库,对象在任何缓存中都不存在除外. 2.LockMode.READ: 越过所有缓存,执行一个版本检查验证内存中对象的版本和库中版本是否一致. 3.LockMode.UPGRADE: 越过所有缓存,进行版本检查并获得数据库级别的悲观UPGRADE锁.等价于JPA中的 LockModeType.READ.如果数据库方言不支持..for Update操作,则自动降格到 LockMode.READ. 4.LockMode.UPGRADE_NOWAIT: 等价于3,会执行..for update nowait操作,如果不能立即获得事务的话,不会等待,而是直接抛 出异常. 5.LockMode.FORCE: 强行增加对象在记录中的版本号,表明已经被当前事务修改.等价于JPA中LockModeType.WRITE 6.LockMode.WRITE: Hibernate写操作时自动获得,应用程序不需要指定.

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate传播session
传播hibernate session 有些操作跨越多个dao,但还要保证事务管理.如何实现? 通过Thread-local传播 在dao中需要访问当前会话,且没有事务边界

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate传播session
通过Thread-local传播(线程本地化) 在dao中需要访问当前会话,且不需要定义事务边界. public class ItemDAO { public Bid getMaxBid(Long itemId) { Session s = getSessionFactory().getCurrentSession(); return (Bid) s.createQuery("...").uniqueResult(); } ... } 在控制器中(Action)或service中,定义是事务的边界. sf.getCurrentSession().beginTransaction(); dao1.xxx(..); dao2.xxx(..); Dao3.xxx(..); .. sf.getCurrentSession().getTransaction().commit(); 注:需要设置hibernate.current_session_context_class=thread

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate传播session
使用JTA传播 在dao中仍然使用sf.getCurrentSession(). 在控制器或service中代码如下: utx=(UserTransaction)newInitialContext().lookup("UserTransaction") utx.begin(); dao1.xxx(); dao2.xxx(); utx.commit(); 若用jta方式部署程序的话,则不必启动jta事务边界处理,因为getCurrentSession()方法总是返 回一个范围化的session并且绑定到当前的jta系统事务上. 注意:Hibernate事务接口和getCurrentSession()以及JTA不能一同使用

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate批量操作
直接在db中更新

Query q = s.createQuery("update Item i set i.isActive = :isActive"); q.setBoolean("isActive", true); int res = q.executeUpdate(); 直接创建新对象 "insert into StolenCreditCard(type, number, expMonth) select c.type, c.number, where …

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate批量操作
批量处理(更新)
ScrollableResults itemCursor = session.createQuery("from Item").scroll(); int count=0; while ( itemCursor.next() ) { Item item = (Item) itemCursor.get(0); modifyItem(item); if ( ++count % 100 == 0 ) {

session.flush(); session.clear();
} } tx.commit(); session.close();

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate批量操作
批量插入 for ( int i=0; i<100000; i++ ) { Item item = new Item(...); session.save(item); if ( i % 100 == 0 ) { session.flush(); session.clear(); }

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate批量操作
使用无状态session Session session = sessionFactory.openStatelessSession(); Transaction tx = session.beginTransaction(); ScrollableResults itemCursor = session.createQuery("from Item").scroll(); while ( itemCursor.next() ) { Item item = (Item) itemCursor.get(0); modifyItem(item); session.update(item); } tx.commit(); session.close();

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate批量操作
使用subselect关联检索策略 <class name="Item" table="ITEM"> <set name="bids" inverse="true" fetch="subselect"> <key column="ITEM_ID"/> <one-to-many class="Bid"/> </set> </class> select i.* from ITEM i select b.* from BID b where b.ITEM_ID in (select i.ITEM_ID from ITEM i) 查询多个Item对象.

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate缓存基础
缓存基础 缓存用于性能优化,非JPA和EJB规范,不同厂商方案不同 缓存维护数据状态在本地,内存或者磁盘 缓存会减少数据库访问 缓存策略与范围 缓存类型 一.事务范围:位于当前工作单元,不能并发访问 二.进程范围:多个工作单元共享,可并发访问,可存储实例本身也可存散列数据,然后在 重新组装 三.集群范围:多个进程和主机间访问,网络通信是重点.需要将数据复制到所有集群中的节点.
缓存和OID: 事务级缓存也用于对象id的使用范围,是理想的缓存 进程级缓存可选择实现id的进程范围存储,也和主键对应.并发工作单元查询同一id对象的话返 回相同的实例.在进程级缓存中的对象也可按值返回,每个工作单元再重新组装形成副本.

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate缓存策略与范围
缓存策略与范围 集群级缓存:始终需要远程通信.
缓存与并发 一级缓存是强制的,他也维护了OID,二级缓存(进程级/集群级)对某些数据来说是有用的. 缓存与事务隔离 应用存在非独占性的数据访问,不该使用进程级缓存(金融系统) 非独占访问典型情况 一、集群应用 二、共享遗留数据 适合二级缓存的类的特征: 一、很少改变 二、不共享的本地数据 三、不重要的数据

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate缓存策略与范围
缓存策略与范围 适合二级缓存的类的特征(参考数据-数据字典): 四、对象数量很少 五、被很多类引用 六、很少被更新 Hibernate缓存架构 1、一级缓存即session. 2、二级缓存是可配的插件,可用于进程/集群范围缓存.他们缓存都是状态(按值返回), 而不是真正的持久化对象.对于特定的数据项来说缓存的并发策略定义了事务的 隔离细节.每个类或者每个集合的二级缓存是可选可配的.每个缓存都使用了自己 的缓存区域. 3、Hibernate还实现了对查询结果集的缓存,他和二级缓存紧密结合.而且需要额外 的两个物理缓存区域来容纳缓存的查询结果和最后更新表的时间戳.

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate缓存架构
二级缓存架构

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate缓存架构
Hibernate二级缓存 1、所有通过同一sf开启的会话共享同一二级缓存 2、对象以拆解的形式存于二级缓存中(拆解是串行化过程,算法更多,更快比java串行) 3、重点在于缓存方案(缓存策略与物理缓存提供商) 4、不同数据需要不同的缓存方案.涉及如下设置: a、是否开启二级缓存 b、Hibernate并发策略 c、缓存过期策略(timerout LRU 内存敏感) d、缓存的物理格式(内存 索引文件 集群替换)
二级缓存安装需要两步: 1、决定使用哪个缓存并发策略 2、配置缓存过期和物理缓存属性(cache provider)

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate缓存架构
Hibernate缓存架构 内置并发策略 并发策略是调解人,负责在缓存中检索数据.对于特定数据项,他也定义了事务隔离的语义.对类 或集合来说使用哪个并发策略需要做出判断. 四个内置的并发策略体现了递减的事务隔离的等级. 1、Transationsal 只在受管环境中使用,如果需要可以确保所有的事务隔离到可重复读,很少更新且防止脏数 据情况下该策略很重要 2、Read-write 该策略维护读已提交隔离级别,使用了时间戳机制只在非集群环境下使用. 3、Nostrict-read-write 不保证在数据库和缓存之间数据的一致性,如果使用的话,应该配置一个高效短期的过期超 时.否则,可能读到脏数据. 4、Read-only 适用于从不发生改变的数据.只对数据进行引用.约束的降低带来了性能提升.
还可以实现自定义策略: org.hibernate.cache.CacheConcurrencyStrategy

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate缓存架构
Hibernate缓存架构 选择缓存供应商 Hibernate要求必须为整个应用选择一个供应商.以下是开源的实现: 1、EHCache 适用于单个虚拟机中单个进程范围,可缓存至内存和磁盘,支持查询缓存(最新版本支持集群 缓存,未测试) 2、OpenSymphony OSCache 在单个虚拟机中缓存至内存或磁盘.支持丰富的过期策略和查询缓存. 3、SwarmCache 基于JGROUPS的集群缓存, 不支持Hibernate查询缓存 4、JBoss Cache 同样基于JGROUPS广播库的完全事务性自我复制集群缓存,支持自我复制、校验、同/异步 通信、乐观/ 悲观锁 不是每个缓存供应商对任何并发策略都支持.结果如下:

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate缓存实践
缓存实践 选择并发缓存策略 类数量有限、很少更改、被多个用户共享,是使用二级缓存的典型 <class ..> <cache usage="read-write"/> </class> 如果需要导航到该类对象或load时,hibernate都会查询二级缓存.使用read-write而不是 nostrict-read-write,是因为他是高并发类并在多个并发事务中共享,读已提交隔离级别足够. 而nostrict-read-write要依赖于过期设置,我们首选应该是数据变更后立即可见.该缓存对于 所有该类的子类都有效,我们不能只缓存某个特定的子类. 此设置缓存所有的该类简单的属性值,但不包括关联实体的状态和集合.集合要求有自己的缓 存区域.
<set name="items"> <cache usage="read-write"/> <key

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate缓存实践
缓存实践 选择并发缓存策略 集合缓存的区域名称是类名加属性名: auction.model.Category.items 该集合缓存只缓存了id,而并没有实例,如果需要Item实例自身也要缓存的话,必须开启Item 类的缓存. <set name="bids"> <cache usage="read-write"/> </set>
<class name=―Bid‖ table=―‖ mutable=―false‖> <cache usage=―read-only‖ /> </class>

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate缓存区域
理解缓存区域 Hibernate在不同区域维护不同的类和集合.区域即命了名的缓存.通过它可引用类和集合还可以设置 区域的缓存的过期策略.区域有两种类型,一种存放拆解的实体数据,另一种只存放id并通过集合连接 在一起. 类缓存区域名是类名. 集合是类名加属性名.
还可以通过设置hibernate.cache.region_prefix属性为特定的sf指定区域前缀.则区域名 变为前缀名+‖.‖+区域名. 此设置对于应用中涉及多个sf有用,否则可能会冲突.接下来配置缓存的物理属性,先选缓存供应 商.

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate设置缓存供应商
设置本地缓存供应商 按以下配置设置: hibernate.cache.provider_class=org.hibernate.cahe.EhCacheProvider EHCache有自己的配置文件,位于类路径跟下,名称为
ehcache.xml: <cache name="auction.model.Category" maxElementsInMemory="500 eternal="true" timeToIdleSeconds="0" timeToLiveSeconds="0" overflowToDisk="false― />

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate-EHCache缓存配置
设置本地缓存供应商(续) 因为该类实例有限,通过设置缓存大小限制大于类实例数来关闭溢出设置,同时设置永不过期 (eternal=true),由于该类缓存并发策略是read-write,所以用超时(timeout)使缓存数据过期是没必 要的.而且也没有其他应用直接在库中修改数据.我们也关闭了基于磁盘的缓存溢出,因为该类的实例有 限内存消耗不是问题. 另外,Bid很小 不可变但数量很多,所以必须要配置内存消耗.我们同时设置过期超时和最大缓存大 小限制: <cache name="auction.model.Bid“ maxElementsInMemory="50000" eternal="false“ timeToIdleSeconds="1800" timeToLiveSeconds="100000“ overflowToDisk="false“/>

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate-EHCache缓存配置
设置本地缓存供应商(续) timeToIdleSeconds:空闲时间(发呆时间) timeToLiveSeconds:存活时间(放入缓存开始计时) maxElementsInMemory:内存中最大元素量(元素量超过该值时,最近最少使用的元素被删除) overflowToDisk:溢出至磁盘(由于与db位于同一机器,关闭该设置,否则,本地访问要快于网络访问)

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate控制二级缓存
控制二级缓存
hibernate.cache.use_second_level_cache=false 该属性可全局控制二级缓存开关.默认情况,映射文件(或其他)的cache元素都会触发二级缓存的加载, 使用该属性可避免删除元素控制二级缓存. sf控制二级缓存: sf.evict(xx.class,id);//删除指定类缓存区域中指定id对象. sf.evict(?org…Category‖);//删除指定类缓存区域的所有缓存的对象. 该操作是非事务性的,没有锁机制. Hibernate提供了CacheMode,可为特定的session激活,他控制和二级缓存交互. s.setCacheMode(CacheMode.IGNORE); s.save(c); 则该对象同时被加入到二级缓存中.

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate控制二级缓存
控制二级缓存 s = sf.openSession(); tx = s.beginTransaction(); s.get(Customer.class,1); new Thread(){ public void run(){ s.. s.get(Customer.class,1); .. } }.start(); s.get(c1);//是否查库?why tx.commit(); s.close();
s = sf.openSession(); tx = s.beginTransaction(); s.get(Customer.class,1); tx.commit(); s.close();

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate控制二级缓存
控制二级缓存 1.CacheMode.NORMAL 默认值 2.CacheMode.IGNORE 从不和二级缓存交互,除了更新时废除数据 3.CacheMode.GET 可以查询,但不添加除了更新时废除数据 4.CacheMode.PUT 从不查询,但查库时添加数据 5.CacheMode.REFRESH 同put,该模式下,hibernate.cache.use_minimal_puts属性被屏蔽.在自我复制缓存 集群缓存下为了强制缓存刷新可使用该模式.

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate缓存查询结果
缓存查询结果 二级缓存是数据共享缓存,当访问未加载的代理类实例或者集合或者按照oid检索的时 候,hiberante都会到一、二级缓存中进行查找.默认情况下,查询结果是不缓存的.如果通过iterator() 方法进行查询,只从数据库中查询主键值.而实体数据会从一、二级缓存中查找. 而缓存查询结果是完全不同的问题.他默认是关闭的,每个HQL,JPA QL,SQL和Criteria总是首先要 访问数据库. 启动查询结果缓存 hibernate.cache.use_query_cache = true q.setCacheable(true); 缓存区域名称不同于类/集合缓存,默认情况下域名为 org.hibernate.cache.QueryCache 该方法在QBC中也可用,JPA使用setHint("org.hibernate.cacheable", true) 也可显式设置区域名称:q.setCacheRegion(―my.cache‖); 不过很少使用,除非有特殊的缓存方案.

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家! Hibernate缓存查询结果
理解查询缓存 当某个查询被首次执行时,该结果被缓存到缓存区域.该区域不同于实体和集合的缓存区域.他的缓存 区域的默认的名字是org.hibernate.cache.QueryCache.也可以显式设置区域名称. categoryByName.setCacheRegion("my.Region") 标准的查询结果缓存区域容纳的是sql语句(携带绑定参数)以及结果集.这并不是全部的SQL结 果集.如果结果集包含实体对象,结果集缓存只存放id值.其他数据在放入缓存时就被销毁了.而二级 缓存的实体缓存区负责缓存实体的状态.这和iterator方法有些相似.所以如果要对某个查询结果进 行缓存的话,一定要将对应的实体缓存(二级缓存)打开,不然会有更多的数据库访问. 如果缓存的查询结果不是实体,而是一些标量值,这些值直接存放在查询结果缓存中. 如果查询结果缓存开启的话,另一个缓存区域也会要求开启-org.hibernate.cache. UpdateTimestampsCache.该缓存是hibernate内置的缓存区域.hibernate是用时间戳区域来决 定缓存的查询结果是否过期(脏了).当重新执行查询时,hibernate会在时间戳缓存中查找最近对查 询表所做的插入、更新和删除的时间戳.若发现时间戳晚于要缓存的查询结果的时间戳,则缓存的结果 就要被丢弃并执行新的查询.这可以确保查询中的任何一个表如果包含了更新的数据的话,hibernate 都不会使用缓存的查询结果. 对于使用查询缓存时,必须所使用Query对象都进行相同的设置: q.setCachable(true);//该方法不仅意味着查询结果可缓存,还表示可到缓存中查询结果!!!. q.setCacheRegion(..);//如果两次的缓存区域设置的不同,同样不能实现查询缓存的效果.

北京传智播客教育 www.itcast.cn

—高级软件人才实作培训专家!

北京传智播客教育 www.itcast.cn


相关文章:
传智播客java ee+就业班
传智播客java ee+就业班_计算机软件及应用_IT/计算机_专业资料。传智播客java ...第三阶段:Struts2+Spring+Hibernate+oracle+AJAX+Lucene 搜索引擎+OSEM 框架 ...
传智播客精品就业班入学测试题
传智播客精品就业班入学测试题最新消息: 最新消息:传智播客入学测试题被选为某...Hibernate、 Spring、 Struts、 Ejb、 JMS、 AJAX 等, 还有各种数据库 Oracle、...
传智播客SCM手把手开发文档
传智播客-Android开发培... 98页 1下载券传​智​播​客​S​C​...Hibernate 全局配置文件 10 3.6 创建项目包结构 11 3.7 开发通用工具类 12 3...
经典学习教程
//www.itcast.cn/itcast_static/AJAXVideo.htm 传智播客 Hibernate 视频教程: http://www.itcast.cn/itcast_static/HibernateVideo.htm 传智播客 Spring2.5 视频...
Hibernate 学习总结(star)
21 第一部分: 第一部分:学习总结一. 说明: 1.目前我使用 hibernate 的版本是 3.6.3 版本。 2.此总结是根据传智播客 Hibernate 教学视频教程写的总结。 3....
传智播客Spring2.5视频教程学习笔记
传智播客Spring2.5视频教程学习笔记_IT/计算机_专业资料。传智播客Spring2.5视频...(JDBCTemplate,HibernateTemplate) 支持与 Struts,Hibernate,JPA 等框架的集成 1.6...
Spring学习
传智播客Hibernate课件 292页 免费 S​p​r​i​n​g​学​习 暂无评价|0人阅读|0次下载|举报文档 s​p​r​i​n​g​的​初​...
Hibernate_基础
传智播客Hibernate课件 288页 1财富值 Struts+Spring+Hibernate整... 16页 免费 Struts2教程 45页 免费如要投诉违规内容,请到百度文库投诉中心;如要提出功能问题或...
编程开发---珍藏版资料下载地址
传智播客 :spring2.3/jdbc/EJB3.0/ajax/hibernate/Struts/java 视频教程》 17.1GB (SPRING2.5/AJAX/JAVA/JNI/FTP/AJAX/ibatis/OA/JDBC)[压缩包] 41.3MB ...
程序员简历模板2014
【项目二】谷度科技资讯播客 开发/测试环境:Struts2、Spring、Hibernate、Junit ...广州传智播客培训中心 培训课程:Java 软件工程师课程培训 培训描述:在培训期间,...
更多相关标签:
传智播客 | 传智播客和育知哪个好 | 传智播客与达内哪家好 | 传智播客官网 | 传智播客ui培训怎么样 | 传智播客就业被辞退 | 传智播客 c | 传智播客java视频 |