Hibernate的1级、2级Cache管理及EhCache的使用

来源:互联网 发布:shell脚本编程pdf 编辑:程序博客网 时间:2024/05/29 15:20

Hibernate的1级、2级Cache管理及EhCache的使用

Cache就是缓存,它往往是提高系统性能的最重要手段,对数据起到一个蓄水池和缓冲的作用。Cache对于大量依赖数据读取操作的系统而言尤其重要。在大并发量的情况下,如果每次程序都需要向数据库直接做查询操作,它们所带来的性能开销显而易见,频繁的网络传输、数据库磁盘的读写操作都会大大降低系统的整体性能。此时,如果能把数据在本地内存中保留一个镜像,下次访问时只需从内存中直接获取,那么显然可以带来显著的性能提升。引入Cache机制的难点是如何保证内存中数据的有效性,否则脏数据的出现将会给系统带来难以预知的严重后果。虽然一个设计得很好的应用程序不用Cache也可以表现出让人接受的性能,但毫无疑问,一些对读操作要求很高的应用程序可以通过Cache取得更高的性能。对于应用程序,Cache通过内存或磁盘保存了数据库中当前有关数据状态,它是一个存于当地的数据备份。Cache位于数据库和应用程序之间,从数据库中更新数据,并给程序提供数据。

Hibernate实现了良好的Cache机制,可以借助Hibernate内部的Cache迅速提高系统数据读取性能。Hibernate中的Cache可分为两层:一级Cache和二级Cache。


一级Cache

Session实现了第一级Cache,它属于事务级数据缓冲。一旦事务结束,这个Cache也随之失效。一个Session的生命周期对应一个数据库事务或一个程序事务。

Session-cache保证在一个Session中两次请求同一个对象时,取得的对象是同一个Java实例,有时它可以避免不必要的数据冲突。另外,它还能保证另一些重要的性能。

在对一个对象循环引用时,不至于产生堆栈溢出。


当数据库事务结束时,对于同一数据库行,不会产生数据冲突,因为对于数据库中的一行,至多有一个对象来表示它。


一个事务中可能会有很多个处理单元,在一个处理单元中做的操作都会立即被另外的处理单元得知。

不用刻意去打开Session-cache,它总是被打开并且不能被关闭。当使用save()、update()或saveOrUpdate()来保存数据更改,或通过load()、find()、list()等方法来得到对象时,对象就会被加入到Session-cache。

如果要同步很大数量的对象,这是需要有效地管理Cache,可以用Session的evict()方法从一级Cache中移除对象。例如:


Session session = HibernateUtil.currentSession();Transaction tx = session.beginTransaction() ;for(int i=0; i<100000 ;i++) {Student stu = new Student();….session.save(stu);}tx.commit();session.close();
 
在保存50 000个对象时,程序可能抛出OutOfMemoryException异常,因为Hibernate在一级Cache缓存了新加入数据库的所有对象。要解决这个问题,首先设置JDBC批处理数量到一个合理的数值(一般是10~20)。在hibernate.properties配置文件中设置如下:
 hibernate.jdbc.batch_size 20
或在hibernate.cfg.xml中设置如下:
<property name=”hibernate.jdbc.batch_size”> 20 </property>
然后在一定的时候提交更改并清空Session的Cache:
 Session session = HibernateUtil.currentSession();Transaction tx = session.beginTransaction() ;for(int i=0; i<100000 ;i++) {Student stu = new Student();….session.save(stu);if(i%20==0) { //每保存完20个Student对象后,进行以下操作session.flush(); //提交更新session.clear(); //清除Cache,释放内存}}tx.commit();session.close();


 

二级Cache
二级Cache是SessionFactory范围内的缓存,所有的Session共享同一个二级Cache。在二级Cache中保存持久性实例的散装形式的数据。二级Cache的内部是如何实现的并不重要,重要的是采用哪种正确的缓存策略,以及采用哪种Cache Providers。持久化不同的数据需要不同的Cache策略,比如说一些因素将影响到Cache策略选择:数据的读/写比例、数据表是否能被其他的应用程序所访问等。对于一些读/写比例高的数据可以打开它的缓存,允许这些数据进入二级缓存容器有利于系统性能的优化;而对于能被其他应用程序访问的数据对象,最好将此对象的二级Cache选项关闭。

设置Hibernate的二级Cache需要分两步进行:首先确认使用什么数据并发策略,然后配置缓存过期时间和设置Cache提供器。


有4种内置的Hibernate数据并发冲突策略,代表了数据库隔离级别,如下所示。

transactional:仅在受管理的环境中可用。它保证可重读的实物隔离级别,可以对读/写比例高、很少更新的数据采用这种策略。


read-write:使用timestamp机制维护读已提交事务隔离级别。可以对读/写比例高、很少更新的数据采用这策略。


nonstrict-read-write:不保证Cache和数据库之间的数据一致性。使用此策略时,应该设置足够短的缓存过期时间,否则可能从缓存中读出脏数据。当一些数据极少改变,并且当这些数据和数据库有一部分不一致但影响不大时,可以使用此策略。


read-only:当确保数据永不改变时,可以使用此策略。


确定了Cache策略之后,就要挑选一个合适高效的Cache提供器,它作为插件被Hibernate调用。Hibernate允许使用下述几种缓存插件。


EhCache:可以在JVM中作为一个简单进程范围的缓存,它可以把缓存的数据放入内存或磁盘,并支持Hibernate中可选用的查询缓存。


OpenSymphony OSCache:和EhCache相似,并且它提供了丰富的缓存过期策略。
SwarmCache:可作为集群范围的缓存,但不支持查询缓存。
JBossCache:可作为集群范围的缓存,但不支持查询缓存。

上述4种缓存插件的对比情况列于表9-3中。
表9-3  4种缓存插件的对比情况

缓 存 插 件
 支 持 只 读
 支持非严格读写
 支 持 读 写
 支 持 事 务
 
EhCache
 是
 是
 是
 
 
OSCache
 是
 是
 是
 
 
SwarmCache
 是
 是
 
 
 
JBossCache
 是
 
 
 是
 

它们的提供器列于表9-4中。
表9-4  缓存策略的提供器

缓 存 插 件
 提供器(Cache Providers)
 
Hashtable(只能测试时使用)
 org.hibernate.cache.HashtableCacheProvider
 
EhCache
 org.hibernate.cache.EhCacheProvider
 
OSCache
 org.hibernate.cache.OSCacheProvider
 
SwarmCache
 org.hibernate.cache.SwarmCacheProvider
 
JBossCache
 org.hibernate.cache.TreeCacheProvider
 

在默认情况下,Hibernate使用EhCache进行JVM级别的缓存。用户可以通过设置Hibernate配置文件中的hibernate.cache.provider_class的属性,指定其他的缓存策略,该缓存策略必须实现org.hibernate.cache.CacheProvider接口。

在Hibernate中使用EhCache

EhCache是一个纯Java程序,可以在Hibernate中作为一个插件引入。它具有运行速度快、结构简单、占用内存小、很小的依赖性、支持多CPU服务器、文档齐全等特点。

在Hibernate中使用EhCache,需要在hibernate.cfg.xml中设置如下:

<property name=” hibernate.cache.provider_class”>org.hibernate.cache.EhCacheProvider</property>
 
EhCacheProvider类位于hibernate3.jar包中,而不是位于ehcache-1.1.jar包中。EhCache有自己的配置文档,名为ehcache.xml。在Hibernate3.x中的etc目录下有ehcache.xml的示范文件,将其复制应用程序的src目录下(编译时会把ehcache.xml复制到WEB-INF/classess目录下),对其中的相关值进行更改以和自己的程序相适合。进行配置后,在ehcache.xml文件中的全部代码如下:
  <diskStore path="d:\\cache"/> //设置cache.data文件的存放位置    <defaultCachemaxElementsInMemory="10000" //缓存中允许创建的最大对象数eternal="false" //缓存中对象是否为永久的timeToIdleSeconds="120" //缓存数据钝化时间(即对象在它过期前的空闲时间)timeToLiveSeconds="120" //缓存数据生存时间(即对象在它过期前的生存时间)overflowToDisk="true"  //是否启用磁盘缓存/>    <cache name="Student"   //用户自定义的Cache配置maxElementsInMemory="10000"eternal="false"timeToIdleSeconds="300"timeToLiveSeconds="600"overflowToDisk="true"/></ehcache>


此外,还需要在持久化类的映射文件中进行配置。例如,Group(班级)和Student(学生)是一对多的关系,它们对应的数据表分别是t_group和t_student。现在要把Student类的数据进行二级缓存,这需要在两个映射文件(Student.hbm.xml和Group.hbm.xml)中都对二级缓存进行配置。

在Group.hbm.xml中配置二级缓存如下:

    ……<hibernate-mapping><class name="Group" table="t_group" lazy="false">……<set name="students" cascade="save-update" inverse="true"   <!--关系由Student维护-->lazy="true"><cache usage="read-write"/>  //<!--集合中的数据将被缓存--><key column="id"/><one-to-many class="Student"/></set></class></hibernate-mapping>……
 
上述文件虽然在<set>标记中设置了<cache usage="read-write"/>,但Hibernate仅把和Group相关的Student的主键id加入到缓存中,如果希望把整个Student的散装属性都加入到二级缓存中,还需要在Student.hbm.xml文件的<class>标记中加入<cache>子标记,如下所示:
<class name="Student" table="t_student" ><cache usage="read-write" /> <!--cache标记需跟在class标记后-->……</class>
 

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 生完孩子腰背疼怎么办 宝宝不肯把屎尿怎么办 存的电话删除了怎么办 脚踝的韧带断了怎么办 买了双鞋子想退怎么办 鞋子大了一码怎么办 nba篮球大师身体素质满了怎么办 钉鞋大了一码怎么办 篮球鞋鞋垫会向里面跑怎么办 穿高跟鞋脚肿了怎么办 衣服弄到单车油怎么办 高低床孩子摔下来怎么办 量血压时老紧张怎么办 牛仔外套的扣子掉了怎么办 裤子的裤筒大了怎么办 衣服拉链驰坏了怎么办 小脚裤裤腿紧了怎么办 地垫粘地板了怎么办 棉麻衬衣皱了怎么办 麻料衣服烫皱了怎么办 在京东买一双奥康鞋没有防伪怎么办 足球鞋丁掉了一颗怎么办 鼻子有点大想变小该怎么办 阿勒泰小东沟风景区边防证怎么办 孩子上一年级了学习很差怎么办 孩子作息时间不规律怎么办 冬天冻脸怎么办小妙招 冬天冻脚怎么办小妙招 冬天脚冷怎么办小妙招 初中生不爱学习父母该怎么办 早孕办公室买新办公桌怎么办 一年级学生专注度差怎么办 pscs6界面字体太小怎么办 psd文件打不开程序错误怎么办 经常熬夜皮肤暗黄怎么办 炎症引起的经期不来怎么办 父母沉迷于炒股该怎么办 宝宝嘴周边红了怎么办 后背被嘴吸出牙印怎么办 宝宝嘴巴周围长湿疹怎么办 宝宝脸蛋都是红红的湿疹怎么办