深入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级别的缓存
- 他是属于进程范围的缓存
启用二级缓存的条件
- 很少被修改
- 很少系统模块都要用到
- 不是私有的数据,是共享的
- 二级缓存的供应商
Hibernate的一些相关信息(续)