Hibernate的一些相关信息(续)
深入Session
session概述
Session接口时Hibernate向应用程序提供的操纵对数据库的最主要的接口,他提供了基本的保存,更新,删除和加载Java对象的方法。
理解Session的缓存、
- 在session借口的实现中包含一些列的Java集合,这些Java集合构成了Session缓存,只要Session实力没有结束生命周期,存放在它缓存中的对象也不会结束生命周期
- 当session的save()方法持久化一个对象时,该对象被载入缓存,以后即使程序中不在引用该对象,只要缓存不清空,该对象仍然处于生命周期中。当时图load()对象时,会判断缓存中是否存在该对象,有则返回。没有在查询数据库
清理Session的缓存
- Session具有一个缓存,位于缓存中的对象称为持久化对象,它和数据库中的相关记录对应,Session能够在某些时间点,按照缓存中对象的变化来执行相关的SQl语句,来同步更新数据库,这一过程被称为清理缓存(flush)
- 默认情况下Session在以下时间点清理缓存:
- 当应用程序调用Transaction的commit()方法时,该方法先其清理缓存(session.flush()),饭后再向数据库提交事务(tx.commit())
- 当应用程序执行一些查询操作时,如果缓存中持久化对象的属性已经发生了变化,会先清理缓存,以保证查询结果能够反映持久化对象的最新状态
- 显式调用Session的flush()方法
- 区别:
- flush:进行清理缓存(此时缓存中饭的数据并不丢失)的操作,让缓存和数据库同步执行一系列的sql语句,但不提交事务;
- commit:先调用flush()方法,然后提交事务,则意味这提交事务对数据库的操作将会永久保存下来
- reresh:刷新,让session和数据库同步,执行查询,把数据库的最新信息显示出来,更新本体缓存的对象状态
- clear:清空缓存,等价于list.removeAll();
利用Session缓存读取持久化对象的数据
缓存的作用:
- 减少访问数据库的频率。
- 保证缓存中的对象与数据库中的相关记录保持同步。
Session执行批量操作
当Session执行批量操作时,应当定期的清理session的缓存下,这样才能保证足够的空间。
Hibernate检索策略
类级别检索策略
默认的检索策略是立即检索。在Hibernate映射文件中,通过<class>上配置lazy属性来确定检索策略。对于session的检索方式,类级别检索策略仅适用于load方法;也就是说,对于get、query建所以,持久化对象都会被立即加载而不管lazy时false还是true,一般来说,我们检索对象就是要访问它,英雌立即检索时通常的选择。由于load方法在检索不到对象时会抛出异常(立即检索的情况下),因此不建议使用load检索;而由于<class>中的lazy属性还影响到多对一及一对一的检索策略,因此使用load方法就更没必要了。
关联级别检索策略
fetch
(默认值select)
Lazy
(默认值是true)
策略
Join
False
采用迫切左外联接检索。
Join
True
采用迫切左外联接检索。
join
Extra
采用迫切左外联接检索。
select
False
采用立即检索
select
True
采用延迟检索
select
Extra
采用延迟检索
c.getOrders().size() 执行 select count(id) from orders where customer_id =?
for(Order o:set){ o.getOrderNumber();} 将执行:
select customer_id , id,order_number ,price from orders where customer_id=?
subselect
false/true/extra
也分为3中情况
嵌套子查询(检索多个customer对象时) Lazy属性决定检索策略)
select customer_id,order_number,price from orders where customer_id
in (select id from customers)
检索策略
优点
缺点
优先考虑使用的场合
立即检索
对应用程序完全透明,不管对象处于持久化状态还是游离状态,应用程序都可以从一个对象导航到关联的对象
(1)select语句多
(2)可能会加载应用程序不需要访问的对象,浪费许多内存空间。
(1)类级别
(2)应用程序需要立即访问的对象
(3)使用了二级缓存
延迟检索
由应用程序决定需要加载哪些对象,可以避免执行多余的select语句,以及避免加载应用程序不需要访问的对象。因此能提高检索性能,并节省内存空间。
应用程序如果希望访问游离状态的代理类实例,必须保证她在持久化状态时已经被初始化。
(1)一对多或者多对多关联
(2)应用程序不需要立即访问或者根本不会访问的对象
迫切左外连接检索
(1)对应用程序完全透明,不管对象处于持久化状态还是游离状态,都可从一个对象导航到另一个对象。
(2)使用了外连接,select语句少
(1)可能会加载应用程序不需要访问的对象,浪费内存。
(2)复杂的数据库表连接也会影响检索性能。
(1)多对一
(2)需要立即访问的对象
(3)数据库有良好的表连接性能。
Hibernate的检索方式
HQL(Hibernate Query Language)
- HQL(Hibernate Query Language)是面向对象的查询语言,它和SQL查询语言有点相似,在Hibernate提供的各种检索方式中,HQL时使用最广的一种检索方式,它有如下功能:
- 在查询语句中设定各种查询条件
- 支持投影查询,即仅检索出对象的部分属性
- 支持分页查询
- 支持连接查询
- 支持分组查询,允许使用having和group by 关键字
- 提供内聚聚集函数,如sum(),min(),max();
- 能够调用用户定义的SQL函数或标准的SQL函数
- 支持子查询
- 支持动态绑定参数
OID检索方式
按照对象的OID来检索对象
QBC检索方式
使用QBC(Query By Criteria)API来检索对象,这种API封装了基于字符串形式的查询语句,提供了更加面向对象的查询接口。
简单的查询
使用别名
对查询结果排序
分页查询
setFirstResult(int firstResult);设定从哪一个对象开始检索,参数firstResult表示这个对象在查询结果中的索引位置,索引位置的起始值为0,默认情况下,Query从查询结果的第一个对象开始检索
setMaxResult(int maxResults);设定一次最多检索出的对象的数目,在默认情况下,Query和Criteria接口检索出查询结果中所有对象
Hibernate检索方式
短语
含义
Expression.eq
等于=
Expression.allEq
使用Map,使用key/value进行多个等于的判断
Expression.gt
大于>
Expression.ge
大于等于>=
Expression.lt
小于<
Expression.le
小于等于<=
Expression.between
对应sql的between子句
Expression.like
对应sql的like子句
Expression.in
对应sql的in子句
Expression.and
and 关系
Expression.or
or关系
Expression.sqlRestriction
Sql限定查询
Expression.asc()
根据传入的字段进行升序排序
Expression.desc()
根据传入的字段进行降序排序
HQL和QBC支持的各种运算
运算类型
HQL运算符
QBC运算方法
含义
比较运算
=
Express.eq()
<>
Express.not(Express.eq())
>=
Express.ge()
<
Express.lt()
<=
Express.le()
is null
Express.isNull()
is not null
Express.isNotNull()
范围运算符
In
Express.in()
not in
Express.not(Express.in())
Between
Express.between()
not between
Express.not(Express.between())
比较运算
=
Express.eq()
<>
Express.not(Express.eq())
>=
Express.ge()
<
Express.lt()
<=
Express.le()
is null
Express.isNull()
is not null
Express.isNotNull()
范围运算符
In
Express.in()
not in
Express.not(Express.in())
Between
Express.between()
not between
Express.not(Express.between())
逻辑
And
Expression.and()|
Expression.conjunction()
Or
Expression.or()|
Expression.disjunction()
Not
Expression.not()
二级缓存
缓存的概念
计算机领域非常通用的概念。它介于应用程序和永久性数据存储源(如硬盘上的文件或者数据库)之间,起作用是降低应用程序直接读写永久性数据库存储源的频率,从而提高应用的运行性能。缓存中的数据是数据存储源中的数据的拷贝。缓存的物理介质通常时内存。
Hibernate中提供了两个级别的缓存
- Session级别的缓存
- 它时属于事务范围的缓存。这一级别的缓存有hibernate管理的,一般情况下需要进行干预
- SessionFactory级别的缓存
- 他是属于进程范围的缓存
启用二级缓存的条件
- 很少被修改
- 很少系统模块都要用到
- 不是私有的数据,是共享的
- 二级缓存的供应商