Hibernate
的一级缓存
是由
Session
提供的,因此它只存在于
Session
的生命周期中,当程序调用
save(),update(),saveOrUpdate()
等方法,及调用查询接口
list,filter,iterate
时,如
Session
缓存中不存在相应的对象,
Hibernate
会把该对象加入到一级缓存中,当
Session
关闭时,该
Session
所管理的一级缓存也会立即被清除。
注意
:Hibernate
的一级缓存是
Session
所内置的,不能被卸载,也不能进行任何配置
一级缓存采用的是
key-value
的
Map
方式来实现的,在缓存实体对象时,对象的主关键字
ID
是
Map
的
key
,实体对象就是对应的
value
。所以说,一级缓存是以实体对象为单位进行存储的,在访问时使用的是关键字
ID
。虽然,
Hibernate
对一级缓存使用的是自动维护的功能,没有提供任何配置功能,但是可以通过
Session
中提供的方法来对一级缓存的管理进行手工干预。
使用
get
方法获得持久化对象时,首先查找
Session
缓存
(
一级缓存
)
是否有该对象,如果有,则获得该对象;如果没有,就会访问数据库,如果数据库中找不到数据,则返回
null
。
load
方法也是获得数据,但不同的地方是
load
方法已经假定数据库中一定存在该数据,如果在数据库中找不到该数据,则会抛出一个
org.hibernate.ObjectNotFoundException
异常。
load
方法获得对象的过程是:
load
方法首先在
Session
缓存中查找对象,如果找不到则查找
SessionFactory
缓存
(
二级缓存
),
如果再找不到则访问数据库。值得注意的是,
load
方法是假定数据库中一定有该数据,所以使用代理来延迟加载对象,只有在程序中使用了该对象的属性
(
非主键属性
)
时,
Hibernate
才会进入
load
方法的获得对象过程。所以说,如果数据库中不存在该记录,异常是在程序访问该对象属性时抛出的,而不是在创建这个对象时就抛出。
Hibernate
中迭代(
Iterate
)查询实体对象
实现
à
1
、查询出我们需要的数据的所有
ID
(
1
条语句)。
2
、根据每个
ID
查询出每个对象(
N
条语句)。
两次迭代(
Iterate
)查询实体对象
à
第二次迭代会发出查询
ID
的语句,然后
Hibernate
会查看缓存中是否有这些
ID
,如果有就不会再发
SQL
语句。
Hibernate
中迭代(
Iterate
)查询普通属性
实现
à
直接根据
ID
满足的条件,查询出所有的对象的属性(即属性集合)。
两次迭代(
Iterate
)查询普通属性
à
两次迭代都会根据
ID
满足的条件,查询出所有的对象的属性(即属性集合)。即不会缓存。
总结:
Hibernate
的一级缓存只会对实体对像的查询进行缓存,不会对对象的普通属性进行缓存。
大批量的数据添加
à
Hibernate
中添加很大量的数据是,默认会把所有添加的对象都缓存起来,这样有可能导致缓存的溢出,处理这种问题时可以确定多少条记录后显示的调用
flush
,并清理缓存。甚至直接使用
JDBC
,如果仍不能满足需求,可以使用数据库的工具,比如:
Oracle SQL Loader
通过
Hibernate
的实现:
for(int i=0; i<10000000;i++){
Student student=new Student();
student.setName(“qq”+i);
session.save(student);
//
每
100
条更新一次
If(i%100==0){
session.flush()
//
清理缓存
session.clear();
}
}
session.getTransaction().commit();
Hibernate
的二级缓存
Hibernate
的二级缓存也称为进程级的缓存或是
sessionFactory
级的缓存,二级缓存可以被所有的
session
共享。二级缓存的生命周期和
sessionFactory
的生命周期是一样的,并且可以通过
sessionFactory
管理二级缓存。二级缓存是缓存实体对象的。缓存可以简单的看成一个
Map
,通过
key
在缓存里面找
value
。
无论
list
,
load
还是
iterate
,只要读出一个对象,都会填充缓存。但是
list
不会使用缓存
,而
iterate
会先取数据库
select id
出来,然后一个
id
一个
id
的
load
,如果在缓存里面有,就从缓存取,没有的话就去数据库
load
。有说法说大型查询用
list
会把整个结果集装入内存,很慢,而
iterate
只
select id
比较好,但是大型查询总是要分页查的,谁也不会真的把整个结果集装进来,假如一页
20
条的话,
iterate
共需要执行
21
条语句,
list
虽然选择若干字段,比
iterate
第一条
select id
语句慢一些,但只有一条语句,不装入整个结果集
hibernate
还会根据数据库方言做优化,比如使用
mysql
的
limit
,整体看来应该还是
list
快。
二级缓存的实现
(EHCache)
à
1
、在
Hibernate
包中的
etc
文件夹下拷贝
ehcache.xml
到
src
下。这个文件的配置可以参考文件中的注释。
2
、在
hibernate.cfg.xml
文件中加入缓存的提供商
<property
name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>3
、启动二级缓存,
<property
name="hibernate.cache.use_second_level_cache">true</property>4
、指定哪些实体需要使用二级缓存
à
可以在映射文件中采用
<cache>
标签指定(这个标签必须在
ID
标签之前)或者这
hibernate.cfg.xml
文件中统一指定
<class-cache
class="com.bjpowernode.hibernate.Student"
usage="read-only"/>
缓存使用的策略,通常采用
read-only
(缓存在内存中是只读的不会改变)和
read-write
(可读可写的)
二级缓存涉及到的一些情况:
*
开启二级缓存,在两个
session
中发
load
(或
get
)语句,第一个事务提交时肯定会发一条
SQL
语句,但是第二个
session
中不会发出
SQL
语句,因为不同的
session
会共享二级缓存中的数据。
*sessionFactory
管理二级缓存:
sessionFactory.evict(Cat.class, catId); //
清除指定ID
的实体
sessionFactory.evict(Cat.class);
//
清除所有实体
sessionFactory.evictCollection("Cat.kittens",
catId); //
清除一个特定实//
体的集合
sessionFactory.evictCollection("Cat.kittens");
//
清除所有实体的集合
*
一级缓存和二级缓存的交互
à
可以通过 session.setCacheMode(CacheMode.IGNORE);
禁止将一级缓存中的数据放到二级缓存之中。如果另外一个session
进行同样的查询会发出SQL
语句。首先一级缓存失效,二级缓存中有没有放入数据,因此会发第二条语句。
例如:如果没有开启二级缓存,进行大批量更新时,通过没更新固定次数后显示调用flush()
和清除一级缓存,可以防止缓存溢出,但是开了二级缓存后,虽然通过以上步骤清除了一级缓存中的数据,但二级缓存中也放了一份数据,这样是无法避免内存溢出的。所以要通过
session.setCacheMode(CacheMode.IGNORE);
禁止将一级缓存中的数据放到二级缓存之中。
Hibernate
的查询缓存
*
缓存的对象
à
1
、普通属性的结果集2
、查询实体对象时会缓存实体对象的ID
*
缓存的声明周期
à
当管理的表发生修改时,查询缓存的生命周期结束。
*
查询缓存的配置
à
在hibernate.cfg.xml
文件中添加
<property
name="hibernate.cache.use_query_cache">true</property>
开启查询缓存,默认为false
在程序中手动的启用
à
query.setCacheable(true)
*
查询缓存的一些使用情况:1
、开启查询缓存,关闭二级缓存,采用了query.list()
查询普通的属性,无论在一个session
还是不同的session
中进行两次查询查询都只发出一条SQL
语句。查询缓存和session
的生命周期没有关系2
、开启查询缓存,关闭二级缓存,两个session
中发query.iterate()
查询,第二个session
会发出查询语句,query.iterate()
查询普通属性它不会使用查询缓存,
查询缓存只对query.list()
起作用
。3
、
开启查询缓存,关闭二级缓存,采用query.list()
查询实体,两个session
中发query.list()
查询,第二个session
会发出N
条SQL
语句(这N
条语句是根据ID
进行查询实体),因为前面说过,查询实体对象时查询缓存会缓存实体对象的id
,第二次执行query.list(),
将查询缓存中的id
依次取出,分别到一级缓存和二级缓存中查询相应的实体对象,如果存在就使用缓存中的实体对象,否则根据id
发出查询学生的语句。如果开启二级缓存就不会发出N+1
条语句了
。
*
总结:
查询缓存通常会和二级缓存一起使用
分享到:
相关推荐
**hibernate缓存策略详解** Hibernate作为Java领域中广泛使用的ORM框架,其在处理大量数据时,为了提高性能和减少数据库的访问压力,引入了缓存机制。本文将深入探讨Hibernate的缓存策略,包括一级缓存、二级缓存...
### Hibernate缓存策略详解 #### 一、理解Hibernate缓存 ##### 1.1 缓存概念 在软件开发领域,缓存技术是一项重要的优化手段,它可以显著提高应用程序的性能和响应速度。Hibernate作为一种持久层框架,其核心功能...
Hibernate缓存原理及调优策略 Hibernate缓存原理调优策略
Hibernate 缓存策略是优化应用程序性能的关键组成部分,尤其是在频繁访问数据库的情况下。缓存可以减少对物理数据库的直接访问,提高响应速度。本文将详细介绍Hibernate的一级缓存和二级缓存。 一级缓存,也称为...
6. hibernate缓存策略.pdf:这可能包含对Hibernate缓存的各种策略(如读写策略、只读策略等)的详细解析,以及如何根据业务需求选择合适的策略。 7. 高并发web架构.pdf:这可能涉及如何在高并发场景下设计和优化Web...
6. Hibernate缓存策略 在Hibernate3之后,官方开始推荐使用二级缓存,因为它的缓存效果更为显著。一级缓存虽然能提高单个Session的效率,但无法解决多线程环境下数据同步的问题。因此,合理地使用二级缓存能够有效地...
### Hibernate缓存技术研究 #### 一、引言 Hibernate是一种强大的对象-关系映射(Object-Relational Mapping,简称ORM)工具,主要用于Java环境下的应用程序。它能够将应用程序中的对象模型映射到关系型数据库的表...
**Hibernate缓存深入详解** 在Java企业级应用开发中,Hibernate作为一款强大的对象关系映射(ORM)框架,极大地简化了数据库操作。然而,随着应用规模的扩大,数据访问性能成为了一个不可忽视的问题。这时,...
二级缓存是 Hibernate 缓存策略的一部分,它在应用程序的多个会话之间共享数据,进一步优化了数据库访问效率。 二级缓存分为以下关键知识点: 1. **一级缓存与二级缓存的区别**: - 一级缓存:每个 Hibernate ...
### Hibernate缓存机制及优化策略 #### 一、概述 Hibernate作为一款优秀的对象关系映射(ORM)框架,在Java开发领域被广泛应用于数据库操作。它提供了丰富的缓存机制来提高应用性能并降低数据库访问压力。本文将...
综上所述,Hibernate缓存机制是提升应用性能的重要手段,通过合理配置缓存策略、优化查询方式、管理数据库连接以及实施有效的监控和调优措施,可以显著提高Hibernate应用的运行效率和用户体验。然而,缓存的使用并非...
二级缓存是Hibernate缓存策略的重要组成部分,它允许我们在多个会话之间共享数据,从而提升应用程序的效率。 Ehcache是Hibernate常用的一种二级缓存实现,它是一个高性能、内存级的缓存解决方案。Ehcache提供了本地...
**Hibernate缓存详解** 在Java开发中,Hibernate作为一款强大的对象关系映射(ORM)框架,极大地简化了数据库操作。为了提高数据访问性能,Hibernate引入了缓存机制,它可以减少对数据库的直接访问,从而提升应用的...
3. **Hibernate缓存策略**: - **只读(Read-only)**:适用于不更新的数据,是最简单且高效的策略。 - **读/写(Read/write)**:适用于需要更新的数据,比只读策略消耗更多资源。 - **非严格读/写(Nonstrict ...
Hibernate缓存机制是提高应用程序性能的关键技术之一,它通过存储数据副本减少对物理数据库的访问。缓存可以分为两层:第一级缓存和第二级缓存。 **第一级缓存**是内置在Session中的,它是不可卸载的,也称为...
**标题:“Hibernate缓存与Spring事务详解”** 在IT领域,尤其是Java开发中,Hibernate作为一款流行的ORM(对象...在实际项目中,需要根据业务需求和场景选择合适的缓存策略和事务处理方式,以达到最佳的开发效果。