理解缓存的定义:

  缓存(Cache): 计算机领域非常通用的概念。它介于应用程序和永久性数据存储源(如硬盘上的文件或者数据库)之间,其作用是降低应用程序直接读写永久性数据存储源的频率,从而提高应用的运行性能。缓存中的数据是数据存储源中数据的拷贝。缓存的物理介质通常是内存。

理解二级缓存的定义:

  Hibernate中提供了两个级别的缓存

    • 第一级别的缓存是 Session 级别的缓存,它是属于事务范围的缓存。这一级别的缓存由 hibernate 管理的,一般情况下无需进行干预
    • 第二级别的缓存是 SessionFactory 级别的缓存,它是属于进程范围的缓存

SessionFactory 的缓存可以分为两类:

    • 内置缓存: Hibernate 自带的, 不可卸载. 通常在 Hibernate 的初始化阶段, Hibernate 会把映射元数据和预定义的 SQL 语句放到 SessionFactory 的缓存中, 映射元数据是映射文件中数据的复制, 而预定义 SQL 语句是 Hibernate 根据映射元数据推到出来的. 该内置缓存是只读的.
    • 外置缓存(二级缓存): 一个可配置的缓存插件. 在默认情况下, SessionFactory 不会启用这个缓存插件. 外置缓存中的数据是数据库数据的复制, 外置缓存的物理介质可以是内存或硬盘

理解二级缓存的并发访问策略

  • 两个并发的事务同时访问持久层的缓存的相同数据时, 也有可能出现各类并发问题.
  • 二级缓存可以设定以下 4 种类型的并发访问策略, 每一种访问策略对应一种事务隔离级别
    • 非严格读写(Nonstrict-read-write): 不保证缓存与数据库中数据的一致性. 提供 Read Uncommited 事务隔离级别, 对于极少被修改, 而且允许脏读的数据, 可以采用这种策略
    • 读写型(Read-write): 提供 Read Commited 数据隔离级别.对于经常读但是很少被修改的数据, 可以采用这种隔离类型, 因为它可以防止脏读
    • 事务型(Transactional): 仅在受管理环境下适用. 它提供了 Repeatable Read 事务隔离级别. 对于经常读但是很少被修改的数据, 可以采用这种隔离类型, 因为它可以防止脏读和不可重复读
    • 只读型(Read-Only):提供 Serializable 数据隔离级别, 对于从来不会被修改的数据, 可以采用这种访问策略(很强,但是性能低)

缓存中存放的数据

  • 适合放入二级缓存中的数据:
    • 很少被修改
    • 不是很重要的数据, 允许出现偶尔的并发问题
  • 不适合放入二级缓存中的数据:
    • 经常被修改
    • 财务数据, 绝对不允许出现并发问题
    • 与其他应用数据共享的数据

缓存提供的供应商

  • Hibernate 的二级缓存是进程或集群范围内的缓存, 缓存中存放的是对象的散装数据
  • 二级缓存是可配置的的插件, Hibernate 允许选用以下类型的缓存插件:
    • EHCache: 可作为进程范围内的缓存, 存放数据的物理介质可以是内存或硬盘, 对 Hibernate 的查询缓存提供了支持
    • OpenSymphony OSCache:可作为进程范围内的缓存, 存放数据的物理介质可以使内存或硬盘, 提供了丰富的缓存数据过期策略, 对 Hibernate 的查询缓存提供了支持
    • SwarmCache: 可作为集群范围内的缓存, 但不支持 Hibernate 的查询缓存
    • JBossCache:可作为集群范围内的缓存, 支持 Hibernate 的查询缓存
  • 4 种缓存插件支持的并发访问策略(x 代表支持, 空白代表不支持)

项目中的配置 (配置进程范围内的二级缓存【配置ehcache缓存】)

(1) 需要引入三个jar包

  • 在hibernate下能找到hibernate-distribution-3.6.10-Final\lib\optional\ehcache\ehcache-1.5.0.jar
  • 在srping下能找到

..\lib\concurrent\backport-util-concurrent.jar

..\lib\jakarta-commons\commons-logging.jar

  • 拷贝到当前工程的lib目录下

(2) 开启二级缓存

  <property name="hibernate.cache.use_second_level_cache">true</property>

(3) 要指定缓存的供应商

  <property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>

(4) 指定使用二级缓存的类

* 方法一 在使用类的*.hbm.xml配置

  • 选择需要使用二级缓存的持久化类, 设置它的二级缓存的并发访问策略,<class> 元素的 cache 子元素表明 Hibernate 会缓存对象的简单属性, 但不会缓存集合属性, 若希望缓存集合属性中的元素, 必须在 <set> 元素中加入 <cache> 子元素
  •  <class name="cn.fuyi.xxx.entity.Person"  table="persons"  lazy="false">
    <!-- 配置类级别的二级缓存 -->
    <cache usage="read-write"/>
    </class> <set name="orders" table="orders" inverse="true" fetch="select" lazy="false">
    <!-- 配置集合级别的二级缓存 -->
    <cache usage="read-write"/>
    </set>

* 方法二  在hibernate.cfg.xml文件中配置(建议)

  <!-- 指定使用二级缓存的类 放在mapping下面 -->

  <!-- 配置类级别的二级缓存 -->
<class-cache class="cn.itcast.c3p0.Customer" usage="read-write"/>
<class-cache class="cn.itcast.c3p0.Order" usage="read-write"/> <!-- 配置集合级别的二级缓存 -->
<collection-cache collection="cn.itcast.c3p0.Customer.orders"
usage="read-write"/>

(5)  配置ehcache默认的配置文件ehcache.xml(名字固定)(放在类路径下)

 ehcache.xml文件

 <diskStore path="D:\cache" />
<cache name=" “
maxElementsInMemory="100“
eternal="false"
timeToIdleSeconds="300“
timeToLiveSeconds="600"
overflowToDisk="true“
diskPersistent="false“ />
</ehcache>

配置ehcache缓存的说明:

  • <diskStore>:指定一个目录, 当 EHCache 把数据写到硬盘上时, 将把数据写到这个文件目录下. 默认是C:\WINDOWS\Temp
  • <defaultCache>: 设置缓存的默认数据过期策略
  • <cache> 设定具体的命名缓存的数据过期策略
  • 每个命名缓存代表一个缓存区域,每个缓存区域有各自的数据过期策略。命名缓存机制使得用户能够在每个类以及类的每个集合的粒度上设置数据过期策略。
  • cache元素的属性   
    • name:设置缓存的名字,它的取值为类的全限定名或类的集合的名字
    • maxElementsInMemory :设置基于内存的缓存中可存放的对象最大数目
    • eternal:设置对象是否为永久的,true表示永不过期,此时将忽略timeToIdleSeconds 和 timeToLiveSeconds属性; 默认值是false
    • timeToIdleSeconds:设置对象空闲最长时间,以秒为单位, 超过这个时间,对象过期。当对象过期时,EHCache会把它从缓存中清除。如果此值为0,表示对象可以无限期地处于空闲状态。
    • timeToLiveSeconds:设置对象生存最长时间,超过这个时间,对象过期。
      如果此值为0,表示对象可以无限期地存在于缓存中. 该属性值必须大于或等于 timeToIdleSeconds 属性值
    • overflowToDisk:设置基于内在的缓存中的对象数目达到上限后,是否把溢出的对象写到基于硬盘的缓存中
    • diskPersistent 当jvm结束时是否持久化对象 true false 默认是false
    • diskExpiryThreadIntervalSeconds 指定专门用于清除过期对象的监听线程的轮询时间
  • 以下属性是必须的:

    • maxElementsInMemory - 在内存中缓存的element的最大数目
    • maxElementsOnDisk - 在磁盘上缓存的element的最大数目
    • eternal - 设定缓存的elements是否永远不过期。如果为true,则缓存的数据始终有效,如果为false那么还要根据timeToIdleSeconds,timeToLiveSeconds判断
    • overflowToDisk - 设定当内存缓存溢出的时候是否将过期的element缓存到磁盘上
  • 以下属性是可选的:
    • timeToIdleSeconds - 当缓存在EhCache中的数据前后两次访问的时间超过timeToIdleSeconds的属性取值时,这些数据便会删除.
    • timeToLiveSeconds - 缓存element的有效生命期
    • diskPersistent - 在VM重启的时候是否启用磁盘保存EhCache中的数据,默认是false。
    • diskExpiryThreadIntervalSeconds - 磁盘缓存的清理线程运行间隔,默认是120秒。每隔120s,相应的线程会进行一次EhCache中数据的清理工作
    • memoryStoreEvictionPolicy - 当内存缓存达到最大,有新的element加入的时候, 移除缓存中element的策略。默认是LRU(最近最少使用),可选的有LFU(最不常使用)和FIFO(先进先出)

查询缓存(Query缓存)

  • 对于经常使用的查询语句, 如果启用了查询缓存, 当第一次执行查询语句时, Hibernate 会把查询结果存放在查询缓存中. 以后再次执行该查询语句时, 只需从缓存中获得查询结果, 从而提高查询性能
  • 查询缓存使用于如下场合:
    • 应用程序运行时经常使用查询语句
    • 很少对与查询语句检索到的数据进行插入, 删除和更新操作
    • 使用查询缓存的步骤
  • 在 hibernate 配置文件中启用查询缓存

<property name="cache.use_query_cache">true</property>

  • 对于希望启用查询缓存的查询语句, 调用 Query setCacheable(true) 方法

测试二级缓存(查询级别的缓存进行测试)

public void classSecondCache(){
Configuration config=new Configuration().configure();
SessionFactory sf=config.buildSessionFactory();
Session session=sf.openSession();
Transaction tx=session.beginTransaction(); //当我第一次执行查询的时候,查询的实体放置到类级别的缓存中
//查询的条件(主键 这个条件放置查询缓存中)
Query query=session.createQuery("select o from Person o");
query.setCacheable(true);
query.list(); tx.commit();
session.close(); session=sf.openSession();
tx=session.beginTransaction();
//"查询缓存"中存放的是查询条件,以该条件(主键)为准,去"类级别的缓存中"查找实体,不查数据库
query=session.createQuery("select o from Person o");
query.setCacheable(true);
query.list();
tx.commit();
session.close();
}

老生常谈的Hibernate二级缓存的更多相关文章

  1. Hibernate ——二级缓存

    一.Hibernate 二级缓存 1.Hibernate 二级缓存是 SessionFactory 级别的缓存. 2.二级缓存分为两类: (1)Hibernate内置二级缓存 (2)外置缓存,可配置的 ...

  2. 配置Hibernate二级缓存时,不能初始化RegionFactory的解决办法

    配置Hibernate 二级缓存时,出现以下bug提示: SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder&quo ...

  3. 配置Hibernate二级缓存步骤

    配置Hibernate二级缓存步骤: 加入二级缓存的jar包及配置文件 jar包位置:hibernate-release-4.1.8.Final\lib\optional\ehcache下所有jar包 ...

  4. Hibernate 二级缓存 总结整理(转)

    和<Hibernate 关系映射 收集.总结整理> 一样,本篇文章也是我很早之前收集.总结整理的,在此也发上来 希望对大家有用.因为是很早之前写的,不当之处请指正. 1.缓存:缓存是什么, ...

  5. Hibernate(十六):Hibernate二级缓存

    Hibernate缓存 缓存(Cache):计算机领域非常通用的概念.它介于应用程序和永久性数据存储源(如磁盘上的文件或者数据库)之间,起作用是降低应用程序直接读取永久性数据存储源的频率,从而提高应用 ...

  6. hibernate二级缓存demo2

    @Test public void hello3(){ Session session=sessionFactory.openSession(); List list = session.create ...

  7. hibernate二级缓存整合

    <?xml version="1.0" encoding="UTF-8"?> <ehcache xmlns:xsi="http:// ...

  8. ssh整合hibernate 使用spring管理hibernate二级缓存,配置hibernate4.0以上二级缓存

    ssh整合hibernate 使用spring管理hibernate二级缓存,配置hibernate4.0以上二级缓存 hibernate  : Hibernate是一个持久层框架,经常访问物理数据库 ...

  9. spring boot集成ehcache 2.x 用于hibernate二级缓存

    https://www.jianshu.com/p/87b2c309b776 本文将介绍如何在spring boot中集成ehcache作为hibernate的二级缓存.各个框架版本如下 spring ...

随机推荐

  1. SGU 105 div.3 找规律

    There is sequence 1, 12, 123, 1234, ..., 12345678910, ... . Given first N elements of that sequence. ...

  2. SqlSever基础 convert 将类型为字符的一列转成Int类型后进行排序

    镇场诗:---大梦谁觉,水月中建博客.百千磨难,才知世事无常.---今持佛语,技术无量愿学.愿尽所学,铸一良心博客.------------------------------------------ ...

  3. SD卡驱动分析(一)

    Android下的SD卡驱动与标准LINUX下的SD卡驱动好像没有太大的区别,这里就以高通的ANDROID 2.3以代表,来简要分析一下LINUX下SD卡驱动的写法.由于小弟的技术有限,分析的有错的地 ...

  4. Python操作文件、文件夹、字符串

    Python 字符串操作 去空格及特殊符号 s.strip().lstrip().rstrip(',') 复制字符串 #strcpy(sStr1,sStr2) sStr1 = 'strcpy' sSt ...

  5. 【转载】如何系统地自学 Python?

    原文:如何系统地自学 Python? 作者:彭猫 本文由 知乎 彭猫 授权发布,版权所有归作者,转载请联系作者! 是否非常想学好 Python,一方面被琐事纠缠,一直没能动手,另一方面,担心学习成本太 ...

  6. CUBRID学习笔记 8 复制数据库

    1  export  database  类似sqlserver的分离数据库 cubrid unloaddb demodb分离后生成三个文件 demodb_objects, demodb_indexe ...

  7. poj 1064 (二分+控制精度) && hdu 1551

    链接:http://poj.org/problem?id=1064 Cable master Time Limit: 1000MS   Memory Limit: 10000K Total Submi ...

  8. Entity Framework 学习初级篇--EntityClient(转)

    摘自:http://www.cnblogs.com/xray2005/archive/2009/05/13/1456374.html System.Data.EntityClient 命名空间是 实体 ...

  9. hd1496---->这道题是水水的数论吗?

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=1496 题意: Consider equations having the following form: ...

  10. luabind 导出string问题

    luabind导出字符串 不能导出char* 会有问题 应该是字符串连接的时候出错了 static _TCHAR* pRetChar = new _TCHAR[10]; memcpy(pRetChar ...