原文:http://blog.csdn.net/tfnew21/archive/2009/02/25/3934055.aspx
在Hibernate 中实现了良好的Cache 机制,可以借助Hibernate内部的Cache提高系统数据读取性能。Hibernate做为一个应用级的数据访问层封装,只能在其作用范围内保持Cache中数据的的有效性,也就是说,在我们的系统与第三方系统共享数据库的情况下,Hibernate的Cache机制可能失效。例如,如果你用access修改了库中的值,那么这就不会更新 JVM中的缓冲池,这就导致了赃数据的产生。
Hibernate在本地JVM 中维护了一个缓冲池,并将从数据库获得的数据保存到池中以供下次重复使用(如果在Hibernate中数据发生了变动,Hibernate同样也会更新池中的数据)。此时,如果有第三方系统对数据库进行了更改,那么,Hibernate并不知道数据库中的数据已经发生了变化,也就是说,池中的数据还是修改之前的版本,下次读取时,Hibernate会将此数据返回给上层代码,从而导致潜在的问题。外部系统的定义,并非限于本系统之外的第三方系统,即使在本系统中,如果出现了绕过Hibernate数据存储机制的其他数据存取手段,那么Cache的有效性也必须细加考量。例如在同一套系统中,基于 Hibernate和基于JDBC的两种数据访问方式并存,那么通过JDBC更新数据库的时候,Hibernate同样无法获知数据更新的情况,从而导致脏数据的出现。
基于Java的Cache实现,最简单是HashTable,hibernate提供了基于Hashtable的Cache 实现机制,不过,由于其性能和功能上的局限,仅供开发调试中使用。同时,Hibernate还提供了面向第三方Cache实现的接口,如JCS、EHCache、OSCache、JBoss Cache、SwarmCache等。
Hibernate中的Cache大致分为两层,第一层Cache在Session实现,属于事务级数据缓冲,一旦事务结束,这个Cache 也就失效。此层Cache 为内置实现,无需我们进行干涉。第二层Cache,是Hibernate 中对其实例范围内的数据进行缓存的管理容器。
12.5.1 二级缓存
在Hibernate早期版本中采用了JCS(Java Caching System -Apache Turbine项目中的一个子项目)作为默认的第二层Cache实现。由于JCS的发展停顿,以及其内在的一些问题(在某些情况下,可能导致内存泄漏以及死锁),新版本的Hibernate已经去除JCS,并用EHCache作为其默认的第二级Cache实现。相对JCS,EHCache更加稳定,并具备更好的缓存调度性能,缺陷是目前还无法做到分布式缓存,如果我们的系统需要在多台设备上部署,并共享同一个数据库,必须使用支持分布式缓存的Cache 实现(如JCS、JBossCache)以避免出现不同系统实例之间缓存不一致而导致脏数据的情况。Hibernate对Cache进行了良好封装,透明化的Cache机制使得我们在上层结构的实现中无需面对繁琐的Cache维护细节。
Hibernate的Session在事务级别进行持久化数据的缓存操作。 当然,也有可能分别为每个类(或集合),配置集群、或JVM级别(SessionFactory级别)的缓存。 甚至可以为之插入一个集群的缓存。需要注意的是缓存永远不知道其他应用程序对持久化仓库(数据库)可能进行的修改(即使可以将缓存数据设定为定期失效)。
通过设置hibernate.cache.provider_class属性中指定org.hibernate.cache.CacheProvider的某个实现的类名,可以选择让Hibernate使用哪个缓存实现。Hibernate内置了一些开源缓存实现,提供对它们的内置支持,如表12-3所示。
表12-3 Hibernate的内置缓存
缓存
提供类
类型
集群安全否
支持查询缓存
Hashtable
org.hibernate.cache.HashtableCacheProvider
内存
否
是
EHCache
org.hibernate.cache.EhCacheProvider
内存,磁盘
否
是
OSCache
org.hibernate.cache.OSCacheProvider
内存,磁盘
否
是
SwarmCache
org.hibernate.cache.SwarmCacheProvider
集群
是
否
JBoss TreeCache
org.hibernate.cache.TreeCacheProvider
集群
是
是
12.5.2 缓存映射
配置缓存映射是通过设置类或者集合映射的“<cache>元素”来设定,例如:
<cache
usage="transactional|read-write|nonstrict-read-write|read-only" (1)
region="RegionName" (2)
include="all|non-lazy" (3)
/>
在上面配置中,其中:
(1) usage(必须)说明了缓存的策略:分别有 transactional、 read-write、 nonstrict-read-write或 read-only。
(2) region (可选, 默认为类或者集合的名字) 指定第二级缓存的区域名。
(3) include (可选,默认为 all) 当属性级延迟抓取打开时, 标记为lazy="true"的实体的属性可能无法被缓存 。
另外可以在hibernate.cfg.xml中指定<class-cache>和 <collection-cache> 元素。 这里的usage 属性指明了缓存并发策略。
12.5.3 只读缓存策略
如果在应用程序只需读取一个持久化类的实例,而无需对其修改, 那么就可以对其进行只读缓存。这是最简单,也是实用性最好的方法。甚至在集群中,它也能完美地运作。设置方法如下:
<class name="com.Person" mutable="false">
<cache usage="read-only"/>
....
</class>
12.5.4 读/写缓存策略
如果应用程序需要更新数据,那么使用读/写缓存策略比较合适。 如果应用程序要求“序列化事务”的隔离级别,那么就决不能使用这种缓存策略。 如果在JTA环境中使用缓存,那么必须指定hibernate.transaction.manager_lookup_class属性的值, 这样,Hibernate才能知道该应用程序中JTA的TransactionManager的具体策略。 在其他环境中,必须保证在Session.close()或Session.disconnect()调用前, 整个事务已经结束。如果想在集群环境中使用此策略,必须保证底层的缓存实现支持锁定(locking)。Hibernate内置的缓存策略并不支持锁定功能。读/写缓存策略的配置方法如下:
<class name="com.Cat" .... >
<cache usage="read-write"/>
<set name="kittens" ... >
<cache usage="read-write"/>
</set>
</class>
12.5.5 非严格读/写缓存策略
如果应用程序只是偶尔需要更新数据(也就是说,两个事务同时更新同一记录的情况很不常见),也不需要十分严格的事务隔离,那么比较适合使用非严格读/写缓存策略。如果在JTA环境中使用该策略, 必须为其指定hibernate.transaction.manager_lookup_class属性的值, 在其他环境中,必须保证在Session.close()或Session.disconnect()调用前,整个事务已经结束。
12.5.6 事务缓存策略
Hibernate的事务缓存策略提供了全事务的缓存支持, 例如对JBoss TreeCache的支持。这样的缓存只能用于JTA环境中,必须为其指定hibernate.transaction.manager_lookup_class属性。
12.5.7 管理缓存
在应用程序中,当给save()、update()或saveOrUpdate()方法传递一个对象时,或使用load()、get()、list()、iterate()或scroll()方法获得一个对象时, 该对象都将被加入到Session的内部缓存中。当flush()方法被调用时,对象的状态会和数据库取得同步。 如果不希望此同步操作发生,或者正处理大量对象、需要对有效管理内存时,可以调用evict()方法,从一级缓存中移除这些对象及其集合。例如:
ScrollableResult cats = sess.createQuery("from Cat as cat").scroll(); //大量数据集
while ( cats.next() ) {
Cat cat = (Cat) cats.get(0);
………
sess.evict(cat);//移除cat
}
Session还提供了一个contains()方法,用来判断某个实例是否处于当前session的缓存中。如若要把所有的对象从session缓存中彻底清除,则需要调用Session.clear()方法。
对于二级缓存来说,在SessionFactory中定义了许多方法, 清除缓存中实例、整个类、集合实例或者整个集合。 例如:
sessionFactory.evict(Cat.class, catId); //清除某个Cat
sessionFactory.evict(Cat.class); //清除所有Cats
sessionFactory.evictCollection("Cat.kittens", catId); //清除某个kittens对象的集合
sessionFactory.evictCollection("Cat.kittens"); //清除所有kittens对象的集合
12.5.8 查询缓存
在Hibernate中查询的结果集也可以被缓存。只有当经常使用同样的参数进行查询时,这才会有些用处。 要使用查询缓存,需要在配置文件中设置,设置方法如下:
hibernate.cache.use_query_cache true
该设置将会创建两个缓存区域,一个用于保存查询结果集
(org.hibernate.cache.StandardQueryCache); 另一个则用于保存最近查询的一系列表的时间戳(org.hibernate.cache.UpdateTimestampsCache)。 需要注意的是在查询缓存中,它并不缓存结果集中所包含的实体的确切状态;它只缓存这些实体的标识符属性的值、以及各值类型的结果。所以查询缓存通常会和二级缓存一起使用。
绝大多数的查询并不能从查询缓存中受益,所以Hibernate默认是不进行查询缓存的。如若需要进行缓存,需要调用 Query.setCacheable(true)方法。这个调用会让查询在执行过程中时先从缓存中查找结果, 并将自己的结果集放到缓存中去。
如果要对查询缓存的失效政策进行精确的控制,你必须调用Query.setCacheRegion()方法, 为每个查询指定其命名的缓存区域。例如:
List cats = sess.createQuery("from Cat cat blog where cat.kittens = :kit")
.setEntity("kittens",kittens)
.setMaxResults(20)
.setCacheable(true)
.setCacheRegion("pages")
.list();
如果查询需要强行刷新其查询缓存区域,那么应该调用Query.setCacheMode(CacheMode.REFRESH)方法。 CacheMode参数用于控制具体的Session如何与二级缓存进行交互。其主要属性如下:
n CacheMode.NORMAL - 从二级缓存中读、写数据。
n CacheMode.GET - 从二级缓存中读取数据,仅在数据更新时对二级缓存写数据。
n CacheMode.PUT - 仅向二级缓存写数据,但不从二级缓存中读数据。
n CacheMode.REFRESH - 仅向二级缓存写数据,但不从二级缓存中读数据。通过 hibernate.cache.use_minimal_puts的设置,强制二级缓存从数据库中读取数据,刷新缓存内容。
这对在其他进程中修改底层数据或对那些需要选择性更新特定查询结果集的情况特别有用。这是对SessionFactory.evictQueries()的更为有效的替代方案,同样可以清除查询缓存区域。
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/tfnew21/archive/2009/02/25/3934055.aspx
分享到:
相关推荐
综上所述,Hibernate缓存机制是提升应用性能的重要手段,通过合理配置缓存策略、优化查询方式、管理数据库连接以及实施有效的监控和调优措施,可以显著提高Hibernate应用的运行效率和用户体验。然而,缓存的使用并非...
本文将深入探讨Hibernate性能优化中的一个重要概念——一级缓存,并结合给出的压缩包文件“hibernate_cache_level1”,来详细解析一级缓存的工作原理及其优化策略。 一级缓存是Hibernate内置的一种缓存机制,它存在...
对于开发和调试,有一些工具如Hibernate Profiler可以帮助我们可视化一级缓存的使用情况,分析性能瓶颈,从而更好地优化应用。 综上所述,Hibernate的一级缓存是提升应用性能的关键要素。通过理解其工作机制并结合...
综上所述,通过学习`hibernate二级缓存示例源码`,我们可以了解到如何在实际项目中配置和使用Hibernate二级缓存,从而提升系统的性能。在实际应用中,应结合具体场景选择合适的缓存策略,以达到最佳的性能优化效果。
#### Hibernate缓存机制概述 Hibernate提供了两种缓存级别:一级缓存和二级缓存。 - **一级缓存**:存在于Session范围内,用于存储实体的实例和状态。当一个实体被加载到Session时,其状态会保存在一级缓存中,...
通过深入理解并实践这个源码实例,开发者可以掌握如何在实际项目中有效利用Hibernate的二级缓存,以及如何结合memcached实现高效的分布式缓存策略。这不仅能够提升应用程序的性能,还能降低对数据库的压力,是现代...
**描述分析:** 描述中的链接指向了一个CSDN博客文章,虽然具体内容没有给出,但可以推测它提供了与Hibernate缓存相关的源码示例。这意味着我们可能要探讨的是如何在实际项目中应用Hibernate的缓存技术,并通过代码...
**hibernate缓存策略详解** Hibernate作为Java领域中广泛使用的ORM框架,其在处理大量数据时,为了提高性能和减少数据库的访问压力,引入了缓存机制。本文将深入探讨Hibernate的缓存策略,包括一级缓存、二级缓存...
二级缓存是Hibernate为了提高性能而引入的一个特性,它存储了已经从数据库中读取的数据,避免了重复的数据库查询。 描述部分提到的“博文链接:https://zhaoshijie.iteye.com/blog/998230”虽然没有提供具体信息,...
《Hibernate缓存机制详解》 Hibernate,作为Java领域中广泛使用的对象关系映射(ORM)框架,极大地简化了数据库操作。其缓存机制是优化性能的关键组成部分,它减少了对数据库的直接访问,提高了数据处理效率。本文...
#### 二、Hibernate缓存概述 Hibernate提供了不同层次的缓存支持: 1. **一级缓存**:即`Session`缓存,它是默认启用的,用于存储当前`Session`中的数据。 2. **二级缓存**:即`SessionFactory`级别的缓存,可选...
通过阅读和运行这个工程,开发者可以更好地理解和掌握Hibernate缓存的实践运用。 总之,理解并有效地使用Hibernate的缓存机制对于提升应用程序性能至关重要。一级缓存和二级缓存相辅相成,前者提供事务级别的高效...
在 Hibernate 中,一级缓存是默认开启的一种缓存机制,对于提高应用程序性能有着重要作用。一级缓存位于 Session 对象中,是每个 Session 的私有缓存,它存储了从数据库中读取的对象实例。 一级缓存的工作原理: 1....
本话题将深入探讨“Hibernate性能测试代码”,以帮助我们理解如何有效地评估和优化Hibernate在实际应用中的表现。 首先,性能测试是软件开发过程中的关键环节,它旨在确定系统的响应时间、吞吐量和资源利用率等指标...
### Hibernate的映射、三态、脏数据、Session缓存...通过上述分析可以看出,Hibernate通过强大的映射机制、状态管理机制、缓存机制等,大大简化了Java应用与数据库之间的交互过程,提高了开发效率和应用程序的性能。
当一个查询被执行并且其结果被缓存后,如果同样的查询再次被执行,Hibernate将直接从缓存中获取结果,而不需要重新执行SQL。这可以显著提高应用性能,尤其是对于那些经常执行但结果很少改变的查询。 五、查询缓存的...
通过上述分析,我们可以看出,Hibernate的二级缓存机制是提高应用性能的重要手段。正确配置和使用二级缓存,能够有效地减少数据库交互,提升系统的响应速度。"ehcache.xml"配置文件和"Hibernate二级缓存架包"提供了...
【Hibernate缓存机制】 Hibernate作为Java领域中广泛使用的对象关系映射(ORM)框架,其缓存机制是提高数据访问性能的关键组成部分。缓存能够减少对数据库的直接访问,从而提高应用性能,降低数据库负载。这里我们...