Hibernate缓存原理:
对于Hibernate这类ORM而言,缓存显的尤为重要,它是持久层性能提升的关键.简单来讲Hibernate就是对JDBC进行封装,以实现内部状态的管理,OR关系的映射等,但随之带来的就是数据访问效率的降低,和性能的下降,而缓存就是弥补这一缺点的重要方法.
缓存就是数据库数据在内存中的临时容器,包括数据库数据在内存中的临时拷贝,它位于数据库与数据库访问层中间.ORM在查询数据时首先会根据自身的缓存管 理策略,在缓存中查找相关数据,如发现所需的数据,则直接将此数据作为结果加以利用,从而避免了数据库调用性能的开销.而相对内存操作而言,数据库调用是 一个代价高昂的过程.
一般来讲ORM中的缓存分为以下几类:
1:事务级缓存: 即在当前事务范围内的数据缓存.就Hibernate来讲,事务级缓存是基于Session的生命周期实现的,每个Session内部会存在一个数据缓 存,它随着 Session的创建而存在,随着Session的销毁而灭亡,因此也称为Session Level Cache.
2:应用级缓存: 即在某个应用中或应用中某个独立数据库访问子集中的共享缓存,此缓存可由多个事务共享(数据库事务或应用事务),事务之间的缓存共享策略与应用的事务隔离 机制密切相关.在Hibernate中,应用级缓存由SessionFactory实现,所有由一个SessionFactory创建的 Session实例共享此缓存,因此也称为SessionFactory Level Cache.
3:分布式缓存:即在多个应用实例,多个JVM间共享的缓存策略.分布式缓存由多个应用级缓存实例组成,通过某种远程机制(RMI,JMS)实现各个缓存实例间的数据同步,任何一个实例的数据修改,将导致整个集群间的数据状态同步.
Hibernate的一,二级缓存策略:
Hibernate中提供了两级Cache,第一级别的缓存是Session级别的缓存,它是属于事务范围的缓存。这一级别的缓存由hibernate管理的,一般情况下无需进行干预;第二级别的缓存是SessionFactory级别的缓存,它是属于进程范围或群集范围的缓存。这一级别的缓存可以进行配置和更改,并且可以动态加载和卸载,属于多事务级别,要防止事务并发性。
缓存是以map的形式进行存储的(key-id,value-object)
一级缓存(Session):
事务范围,每个事务(Session)都有单独的第一级缓存.
一级缓存的管理:当应用程序调用Session的save()、update()、saveOrUpdate()、get()或load(),以及调用查 询接口的 list()、iterate()--(用的是n+1次查询,先查id)或filter()方法时,如果在Session缓存中还不存在相应的对 象,Hibernate就会把该对象加入到第一级缓存中。当清理缓存时,Hibernate会根据缓存中对象的状态变化来同步更新数据库。 Session为应用程序提供了两个管理缓存的方法: evict(Object obj):从缓存中清除参数指定的持久化对象。 clear():清空缓存中所有持久化对象,flush():使缓存与数据库同步。
当查询相应的字段如(name),而不是对象时,不支持缓存。
二级缓存(SessionFactory):
Hibernate的二级缓存策略的一般过程如下:
1:条件查询的时候,总是发出一条select * from table_name where …. (选择所有字段)这样的SQL句查询数据库,一次获得所有的数据对象(这个问题要考虑,如果你查询十万条数据时,内存不是被占用)。
2:把获得的所有数据对象根据ID放入到第二级缓存中。
3: 当Hibernate根据ID访问数据对象的时候,首先从Session一级缓存中查;查不到,如果配置了二级缓存,那么从二级缓存中查;查不到,再查询数据库,把结果按照ID放入到缓存。
4:删除、更新、增加数据的时候,同时更新缓存。
Hibernate的二级缓存策略,是针对于ID查询的缓存策略,对于条件查询则毫无作用。为此,Hibernate提供了针对条件查询的Query Cache。
Q:什么样的数据适合存放到第二级缓存中?
1.很少被修改的数据
2.不是很重要的数据,允许出现偶尔并发的数据
3.不会被并发访问的数据
4.参考数据,指的是供应用参考的常量数据,它的实例数目有限,它的实例会被许多其他类的实例引用,实例极少或者从来不会被修改。
不适合存放到第二级缓存的数据?
1 经常被修改的数据
2 财务数据,绝对不允许出现并发
3 与其他应用共享的数据。
常用的缓存插件 Hibernater 的二级缓存是一个插件,下面是几种常用的缓存插件:
EhCache:可作为进程范围的缓存,存放数据的物理介质可以是内存或硬盘,对Hibernate的查询缓存提供了支持。
OSCache:可作为进程范围的缓存,存放数据的物理介质可以是内存或硬盘,提供了丰富的缓存数据过期策略,对Hibernate的查询缓存提供了支持。
SwarmCache:可作为群集范围内的缓存,但不支持Hibernate的查询缓存。
JBossCache:可作为群集范围内的缓存,支持事务型并发访问策略,对Hibernate的查询缓存提供了支持。
配置二级缓存的主要步骤:
1 选择需要使用二级缓存的持久化类,设置它的命名缓存的并发访问策略。这是最值得认真考虑的步骤。
2 选择合适的缓存插件,然后编辑该插件的配置文件。
EHCache配置:
hibernate.cfg.xml
1
2
3
4
5
6
7
8
9
10
11
12
|
<
hibernate-configuration
>
<
session-factory
>
<!-- 设置二级缓存插件EHCache的Provider类-->
<
property
name
=
"hibernate.cache.provider_class"
>
org.hibernate.cache.EhCacheProvider
</
property
>
<!-- 启动"查询缓存" -->
<
property
name
=
"hibernate.cache.use_query_cache"
>
true
</
property
>
</
session-factory
>
</
hibernate-configuration
>
|
ehcache.xml
1
2
3
4
5
|
<
ehcache
>
<!-- maxElementsInMemory为缓存对象的最大数目, eternal设置是否永远不过期,timeToIdleSeconds对象处于空闲状态的最多秒数,timeToLiveSeconds对象处于缓存状态的最多秒数 -->
<
diskStore
path
=
"java.io.tmpdir"
/>
<
defaultCache
maxElementsInMemory
=
"10000"
eternal
=
"false"
timeToIdleSeconds
=
"300"
timeToLiveSeconds
=
"600"
overflowToDisk
=
"true"
/>
</
ehcache
>
|
****.hbm.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<?
xml
version
=
"1.0"
encoding
=
'UTF-8'
?>
<!
DOCTYPE
hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<
hibernate-mapping
>
<
class
>
<!-- 设置该持久化类的二级缓存并发访问策略 read-only read-write nonstrict-read-write transactional-->
<
cache
usage
=
"read-write"
/>
</
class
>
</
hibernate-mapping
>
|
整理资料来源于网上