Hibernate缓存

Hibernate缓存在工作面试的时候很可能会遇到的问题。

缓存其实就是一块内存空间,充当数据库的内存中的一个临时的容器。

一:hibernate缓存是怎样的?

   Hibernate缓存提供了两种缓存:一级缓存和二级缓存。

1 一级缓存又称事务级缓存,Session的缓存。

    在Hibernate中一级缓存存是基于Session的生命周期实现的,每一个Session会在内部维护一个数据缓存,她随着Session的创建而创建,销毁而销毁。

    一级缓存是必须的,在同一个一级缓存中,每一个持久化类的对象都是唯一的(都有唯一的OID)。   

2 二级缓存又称应用级缓存 SessionFactory的缓存 。

   在Hibernate中二级级缓存是由SessionFactory实现,所有用一个SessionFactory创建的Session对象共享此缓存。

   由于SessionFactory对象的生命周期和应用程序的整个过程对应,因此Hibernate二级缓存是进程范围或者集群范围的缓存,有可能出现并发问题,因此需要采用适当的并发访问策略,该策略为被缓存的数据提供了事务隔离级别。 

  第二级缓存是可选的,是一个可配置的插件,默认下SessionFactory不会启用这个插件。

什么样的数据适合存放到第二级缓存中?   
  1) 很少被修改的数据   
  2) 不是很重要的数据,允许出现偶尔并发的数据   
  3) 不会被并发访问的数据   
  4) 常量数据   
不适合存放到第二级缓存的数据?   
  1) 经常被修改的数据   
  2) 绝对不允许出现并发访问的数据,  
  3) 与其他应用共享的数据。

 

二:为什么我们要使用Hibernate缓存?

            Hibernate就是对JDBC进行的封装 带来的就是数据访问效率的降低,和性能的下降 对于Hibernate这类ORM而言,缓存显的尤为重要,它是持久层性能提升的关键。

    1 Hibernate是一个持久层框架,经常访问物理数据库。

  2 为了降低应用程序对物理数据源访问的频次,从而提高应用程序的运行性能。

  3 缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据。

三:怎样使用hibernate缓存?

 二级缓存:

1 开始缓存:

为了开启二级缓存,需要在hibernate.cfg.xml文件中配置如下属性:

1 <!-- 开启二级缓存 -->
2         <property name="cache.use_second_level_cache">true</property>

一旦开启了二级缓存,并设置了对某个持久化实体类启动缓存,SessionFactory就会缓存应用访问过的该实体类的每个对象,除非缓存的数据超出缓存空间。

2 在实际应用中,一般不需要开发者自己实现缓存,直接使用第3方提供的开源缓存实现即可。因此在hibernate.cfg.xml文件中设置开启缓存后,还需要设置使用哪种缓存实现类。配置如下:

1 <!-- 设置二级缓存的实现类 -->
2         <property name="cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>

 

 

需要注意的是:

3 实际上在项目中使用EHCache缓存实现,仅仅复制lib\optional\下对应缓存的JAR包还不够,应用EHCache还需要依赖于commons-logging.jar,backport-util-concurrent.jar两个工具包。

 

4 将缓存实现所需要的配置文件添加到系统的类加载路径中,对于EHCache缓存,它还需要一个ehcache.xml配置文件:

 

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <ehcache>
 3     <diskStore path="D:/path"/>       <!-- 启用磁盘缓存的位置-->
 4     <defaultCache
 5         maxElementsInMemory="10000"
 6         eternal="false"
 7         timeToIdleSeconds="120"
 8         timeToLiveSeconds="120"
 9         overflowToDisk="true"
10         />
11         <!-- maxElementsInMemory 设置缓存中最多可放多少个对象 -->
12         <!-- eternal 设置缓存是否永久有效 -->
13         <!-- timeToIdleSeconds 设置缓存的对象多少秒没有被使用就会清理掉 -->
14         <!-- timeToLiveSeconds 设置缓存的对象在销毁之前可以缓存多少秒 -->
15         <!-- overflowToDisk 设置当内存中缓存的记录达到maxElementsInMemory 时是否被持久化到硬盘中,保存路径由<diskStore../>元素指定 -->
16 </ehcache>

 

 

 

5 在实体的缓存策略放在不同的映射文件中分别管理:

 

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE hibernate-mapping PUBLIC 
 3     "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 4     "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
 5     
 6     <hibernate-mapping>
 7     
 8     <class name="com.cy.beans.Author" table="t_author" catalog="j2ee">   <!-- catalog数据库 -->
 9       <!-- 设置缓存策略 -->
10         <cache usage="read-only"/>  <!--   这里-->
11      
12               <id name="id" type="java.lang.Long"><!-- 此行的ID,为对象的属性ID -->
13                   <column name="id"></column><!-- 此行的ID,为表字段ID -->
14                   <generator class="increment"></generator><!-- 给id指定生成策略 -->
15               </id>
16     
17               <property name="authorName" type="java.lang.String">
18                  <column name="authorName"></column>
19               </property>
20               
21          <!--lazy :lazy是延时的意思,如果lazy=true,那么就是说数据库中关联子表的信息在hibernate容器启动的时候不会加载,而是在你真正的访问到字表非标识字段的时候,才会去加载。
22                                                 反之,如果lazy=false的话,就是说,子表的信息会同主表信息同时加载  
23                    Hibernate3.x,lazy默认是true;
24                    -->
25          <!-- inverse:hibernate双向关系中的基本概念。inverse的真正作用就是指定由哪一方来维护之间的关联关系。当一方中指定了“inverse=false”(默认),那么那一方就有责任负责之间的关联关系 -->
26         
27     <set name="books" table="t_book" cascade="all" inverse="true" lazy="false"><!-- set映射节点 -->
28              <key column="fk_author_id"></key><!-- 外键 -->
29              <one-to-many class="com.cy.beans.Book"/><!--one-to-mang节点  -->
30     </set>
31     </class>
32      
33     </hibernate-mapping>

缓存同步策略决定了数据对象在缓存中的存取规则.Hibernate中提供了4种不同的缓存同步策略

- read-only:只读.对于不会发生改变的数据可使用

- nonstrict-read-write:如果程序对并发访问下的数据 同步要求不 严格,且数据更新频率较低,采用本缓存 同步策略可获得较 好性能

- read-write:严格的读写缓存.基于时间戳判定机制,实现了“read committed”事务隔离等级.用于对数据同步要求的情况,但支持分布式缓存,实际应用中使用最多的缓存同步策略.

- transactional:事务型缓存,必须运行在JTA事务环境中.此缓存中, 缓存的相关操作被添加到事务中,如事务失败,则缓冲池的数据 会一同回滚到事务的开始之前的状态.事务型缓存实现了 “Repeatable read”事务隔离等级,有效保证了数据的合法性, 适应于对关键数据的缓存,Hibernate内置缓存中,只有 JBossCache支持事务型缓存.

 

posted @ 2015-12-17 22:29  NAYNEHC  阅读(291)  评论(0编辑  收藏  举报