作者:IT168 飞飞 2006-10-17
【IT168 技术文档】摘要:很长时间以来,笔者就想写写关于Hibernate缓存的一些文字,今天有这个不可多得的机会让我谈谈对它的一些想法。Hibernate缓存机制对Hibernate的性能发挥一直处于一个极其重要的作用,它是持久层性能提升的关键。对很多学习或使用Hibernate的朋友一来,还不一定真正的了解或使用她。现在大家就随我一起看看揭开她神秘面纱那张未知的“脸”。
个人备注:二级缓存与查询缓存---二级缓存-查询关联的多个对象中,只要有对象被缓存性能就会提高,而查询缓存只有关联的对象都被缓存性能才能提高,不然则和没有使用查询缓存一样的,甚至有可能降低性能。
1:Hibernate缓存概述
首先在介绍Hibernate缓存之前,笔者在这里做一个小小的比喻,让大家先知道利用缓存的好处。
这个比喻设计的事物有四个,一个是消费者,一个是该消费者附近的电脑城,一个是联想笔记本,一个是联想公司。笔记本是现在普及的商品,消费者想要去买一台联想笔记本,大家想想看,是去附近的电脑城买得快?还是去联想公司买得快?..当然是在电脑城买得快咯,总不能跑到联想公司去买吧?在这里消费者被比做应用程序,电脑城被比做缓存,联想笔记本被比做数据,联想公司被比做数据库。正像我们比喻的那样,应用程序查找我们需要的数据是从缓存中找得快,还是去数据库找得快?答案应该就不用我讲了吧!
缓存是介于物理数据源与应用程序之间,是数据库数据在内存中的存放临时copy的容器,是其作用是为了减少应用程序对物理数据源访问的次数,从而提高了应用的运行性能。
Hibernate在进行读取数据的时候,根据缓存机制在相应的缓存中查询,如果在缓存中找到了需要的数据(我们把这称做“缓存命中”),则就直接把命中的数据作为结果加以利用,避免的了建立数据库查询的性能损耗。说白话点就是,数据放在缓存中,当应用程序还需要他们的时候,就不必再去查数据库了,根据缓存策略从内存中查找速度就会快很多了。
2:Hibernate缓存分类
Hibernate缓存我们通常分两类,一类称为一级缓存也叫内部缓存,另一类称为二级缓存。Hibernate的这两级缓存都位于持久化层,存放的都是数据库数据的拷贝,那么它们之间的区别是什么呢?为了理解二者的区别,需要深入理解持久化层的缓存的一个特性:缓存的范围。
缓存的范围决定了缓存的生命周期以及可以被谁访问。缓存的范围分为三类。
(1) 事务范围:缓存只能被当前事务访问。缓存的生命周期依赖于事务的生命周期,当事务结束时,缓存也就结束生命周期。在此范围下,缓存的介质是内存。事务可以是数据库事务或者应用事务,每个事务都有独自的缓存,缓存内的数据通常采用相互关联的的对象形式, 一级缓存就属于事务范围。
(2) 应用范围:缓存被应用范围内的所有事务共享。这些事务有可能是并发访问缓存,因此必须对缓存采取必要的事务隔离机制。缓存的生命周期依赖于应用的生命周期,应用结束时,缓存也就结束了生命周期,二级缓存存在于应用范围。
(3) 集群范围:在集群环境中,缓存被一个机器或者多个机器的进程共享。缓存中的数据被复制到集群环境中的每个进程节点,进程间通过远程通信来保证缓存中的数据的一致性,缓存中的数据通常采用对象的松散数据形式,二级缓存也存在与应用范围。
注意:对大多数应用来说,应该慎重地考虑是否需要使用集群范围的缓存,因为访问它的速度不一定会比直接访问数据库数据的速度快多少,再加上集群范围还有数据同步的问题,所以应当慎用。
持久化层可以提供多种范围的缓存。如果在事务范围的缓存中没有查到相应的数据,还可以到应用范围或集群范围的缓存内查询,如果还是没有查到,那么只有到数据库中查询了。
3:Hibernate缓存运用与管理
本小节,我们来看看Hibernate的缓存管理,除了我们通常分的两类缓存外,笔者再介绍“查询缓存”,它依赖于二级缓存。
内部缓存:前面我们提到内部缓存是属于事物级缓存,在正常的情况下是由Hibernate自动维护的。当然在特殊的情况下需要我们进行手动维护,Hibernate就提供了以下几种方法供开发者选择:
(1)Session.evict(XXX)
将某个特定的对象从内部缓存中清除,上述的XXX 为对象的实例名。使用此方法有两种适用情形,一是在特定的操作(如批量处理),需要及时释放对象占用的内存维持系统的稳定性,笔者的关于批处理的文章中就运用了此方法,有兴趣的朋友可关注IT168“国庆加油站”技术栏目。二是不希望当前Session继续运用此对象的状态变化来同步更新数据库。 (2)Session.clear()
清除缓存中的所有持久化对象。
二级缓存:在第2节的论述中我们知道,二级缓存涵盖了应用范围与集群范围。这里问题就来了,我们什么情况下要使用二级缓存?如果满足以下条件,则可以将其纳入二级缓存:(1)数据不会被第三放修改
(2)同一数据系统经常引用
(3)数据大小在可接受范围之内
(4)非关键数据,或不会被并发的数据
Hibernate本身并不提供二级缓存的产品化实现,而是为众多支持Hibernate的第三方缓存组件提供整和接口。笔者这里仅仅介绍现在主流的EHCache,它更具备良好的调度性能。
首先,Hibernate启用二级缓存,需要的在主配置文件hibernate.cfg.xml中配置以下参数(以EHCache为例子,使用Hibernate3
<hibernate-configuration>
<session-factory>
…………
<property name=”hibernate.cache.provider_class”>
org.ehcache.hibernate.Provider
</property>
…………
</session-factory>
</hibernate-configuration>
另外还需要对ehcache.xml进行配置,这是一个单独的xml文件,示例如下:
ehcache.xml
<defaultCache
maxElementsInMemory="10000"
//缓存中最大允许创建的对象数
eternal="false"
//缓存中对象是否为永久的,如果是,超时设置将被忽略,对象从不过期
timeToIdleSeconds="120"
//缓存数据钝化时间(设置对象在它过期之前的空闲时间)
timeToLiveSeconds="120"
//缓存数据的生存时间(设置对象在它过期之前的生存时间)
overflowToDisk="true"
//内存不足时,是否启用磁盘缓存
/>
然后呢,我们还需要在映射文件中指定的映射实体的缓存同步策略(以下只列出核心配置,以供大家参考):
…………
<class name=”com.tenly.bean.Student”>
<cache usage=”read-write”>
…………
<set name=”classroom”……>
<cache usage=”read-only”>
…………
</set>
</class>
…………
上面提到read-write、read-only是什么?这就是缓存的同步策略,下面我们来仔细的看看Hibernate提供的几钟缓存策略:
(1) read-only
只读。对于不会发生改变的数据,可使用只读型缓存。
(2)nonstrict-read-write
不严格可读写缓存。如果应用程序对并发访问下的数据同步要求不是很严格的话,而且数据更新操作频率较低。采用本项,可获得良好的性能。
(3) read-write
对于经常被读但很少修改的数据,可以采用这种隔离类型,因为它可以防止脏读这类的并发问题.
(4)transactional(事物型)
在Hibernate中,事务型缓存必须运行在JTA事务环境中。
查询缓存:我们前面提到查询缓存(Query Cache)依赖二级缓存,这到底是怎么回事呢?我看看二级缓存策略的一般过程:
(1) Hibernate进行条件查询的时候,总是发出一条select * from XXX where …(XXX为 表名,类似的语句下文统称Select SQL)这样的SQL语句查询数据库,一次获得所有的符合条件的数据对象。
(2) 把获得的所有数据对象根据ID放入到第二级缓存中。
(3) 当Hibernate根据ID访问数据对象的时候,首先从内部缓存中查找,如果在内部缓存中查不到就配置二级缓存,从二级缓存中查;如果还查不到,再查询数据库,把结果按照ID放入到缓存。
(4)添加数据、删除、更新操作时,同时更新二级缓存。这就是Hibernate做批处理的时候效率不高的原因,原来是要维护二级缓存消耗大量时间的缘故。
我们看到这个过程后,可以明显的发现什么?那就是Hibernate的二级缓存策略是针对ID查询的策略,和对象ID密切相关,那么对于条件查询就怎么适用了。对于这种情况的存在,Hibernate引入了“查询缓存”在一定程度上缓解这个问题。
那么我们先来看看我们为什么使用查询缓存?首先我们来思考一个问题,假如我们对数据表Student进行查询操作,查找age>20的所有学生信息,然后纳入二级缓存;第二次我们的查询条件变了,查找age>15的所有学生信息,显然第一次查询的结果完全满足第二次查询的条件,但并不是满足条件的全部数据。这样的话,我们就要再做一次查询得到全部数据才行。再想想,如果我们执行的是相同的条件语句,那么是不是可以利用之前的结果集呢?
Hibernate就是为了解决这个问题的而引入Query Cache的。
查询缓存策略的一般过程如下:
(1)Query Cache保存了之前查询的执行过的Select SQL,以及结果集等信息,组成一个Query Key。(2)当再次遇到查询请求的时候,就会根据Query Key 从Query Cache找,找到就返回。但 是两次查询之间,数据表发生数据变动的话,Hibernate就会自动清除Query Cache中对应的Query Key。
我们从查询缓存的策略中可以看出,Query Cache只是在特定的条件下才会发挥作用,而且要求相当严格:
(1)完全相同的Select SQL重复执行。
(2)重复执行期间,Query Key对应的数据表不能有数据变动(比如添、删、改操作)
为了启用Query Cache,我们需要在hibernate.cfg.xml中进行配置,参考配置如下(只列出核心配置项):
<hibernate-configuration>
<session-factory>
…………
<property name=”hibernate.cache.user_query_cache”>true</property>
…………
</session-factory>
</hibernate-configuration>
应用程序中必须在查询执行之前,将Query.Cacheable设置为true,而且每次都应该这样。比如:
………
Query query=session.createQuery(hql).setInteger(0.15);
query.setCacheable(true);
………
4:编后语
关于Hibernate缓存的讨论就告一段落了,在实际开发中,运用好缓存可以让你的系统性能得到良好的提升。可缓存也有它的局限性,什么情况用什么情况不用,都要结合实际情况来考量。如果违背了相关的缓存机制,可能会得到负面效果,所以充分考虑实际情况来灵活运用缓存并发挥它的优势,这是我们需要做得更多的。
分享到:
相关推荐
讨论了缓存机制(一级缓存和二级缓存)、批处理、延迟加载和实体状态管理等性能优化策略。 ### 8. 对比其他ORM框架 对比 Hibernate 与其他 ORM 框架,如 MyBatis、EclipseLink 和 JDO,在易用性、灵活性、性能和...
文件`hibernate_fetch_1`与`hibernate_query_cache`涉及到的是Hibernate的数据检索和查询缓存。Hibernate提供了多种加载策略,包括立即加载(Eager Fetching)和延迟加载(Lazy Loading)。立即加载会一次性获取...
在Java的持久化框架中,Hibernate是一个非常重要的角色,它提供了强大的对象关系映射(ORM)功能,使得开发者能够方便地在Java应用中操作...深入研究Hibernate的文档和实践案例,将有助于进一步提高我们的开发技能。
### Hibernate 3.2.2 参考文档精要解析 #### 引言与初次接触Hibernate Hibernate作为一款流行的Java...通过深入研究这份文档,开发者可以更加熟练地掌握Hibernate的使用技巧,从而在项目中发挥出更高的效率和质量。
本文将围绕Spring如何管理和驱动Hibernate4进行详细的讨论。 首先,Spring作为一个灵活的IoC(Inversion of Control)容器,它不仅管理着应用对象的生命周期,还负责整合各种ORM框架,包括Hibernate。Spring的ORM...
下面将详细讨论 Hibernate 3.2 源码中的关键知识点: 1. **对象关系映射(ORM)**:Hibernate 提供了一种机制,将Java类映射到数据库表,使得开发者可以使用面向对象的方式来操作数据库,而无需编写大量SQL语句。 ...
6. **缓存机制**:分析Hibernate的缓存策略,包括一级缓存和二级缓存,以及如何利用缓存提高性能。 7. **性能优化**:提供优化Hibernate应用的技巧,如延迟加载、批处理更新、预加载等策略,以及如何通过SQL优化来...
【描述】:这个项目是一个基于Java技术栈的论坛系统实现,主要利用了Hibernate ORM框架与JSP(JavaServer Pages)进行开发,是适合学生作为毕业论文项目的实例。它展示了如何将数据库操作与Web界面相结合,为用户...
8. **第二级缓存和查询缓存**:讨论Hibernate的缓存机制,如何使用第二级缓存提高性能,以及查询缓存如何减少数据库查询次数。 9. **性能优化**:提供一系列优化策略,如延迟加载、批处理、连接池配置等,帮助...
4. **案例研究**:通过实际项目案例,展示Hibernate在不同场景下的应用。 这些电子书全集将帮助开发者从多个角度全面掌握Hibernate,无论你是初学者还是经验丰富的开发者,都能从中受益匪浅。通过深入阅读和实践,...
8. **性能优化**:学习如何通过缓存机制(一级缓存和二级缓存)、批处理和延迟加载等技术提升Hibernate的性能。 **标签:“源码”和“工具”** 这表明文章可能包含了示例代码,并且可能会讨论如何将这些知识应用于...
6. 查询机制:深入研究Hibernate的查询功能,包括HQL的高级特性,如分页查询、关联查询、子查询以及动态查询。此外,还会涉及Criteria API和JPA的 Criteria 查询。 7. 关联映射:介绍不同类型的关联关系(一对一、...
### 基于Hibernate的效率查询的研究和应用 #### 摘要 本文详细探讨了当前流行的Hibernate映射框架,并结合某通信企业的电子运行维护系统(E2OMS)的实际开发过程,提出了一个基于Hibernate的数据持久层解决方案。该...
6. **缓存机制**:介绍Hibernate的一级缓存和二级缓存,以及如何配置和优化缓存以提高应用程序性能。 7. **性能优化**:讨论最佳实践,如延迟加载、批处理更新、连接池的使用,以及如何通过分析和调整来优化数据库...
描述中提到,这个实例使用了MySQL数据库,这意味着我们将讨论如何配置Hibernate以与MySQL配合工作,并执行CRUD(创建、读取、更新和删除)操作。同时,源代码有详细的注释,这意味着初学者可以通过阅读代码和注释来...
标题“Lucene Hibernate”揭示了我们讨论的核心主题:如何将Apache Lucene这个强大的全文搜索引擎与Hibernate这款流行的Java对象关系映射(ORM)框架相结合。在这个例子中,我们将深入探讨这两个技术的集成,以及...
我们可以深入讨论Hibernate的相关概念、功能、优点以及如何与SQL Server 2008集成。 **文件名分析:** 文件名为“SSHDemo.rar”和“新建文件夹.rar”。"SSHDemo"可能是一个SSH(Spring、Struts、Hibernate)架构的...
7. **缓存机制**:解释了Hibernate缓存的实现原理及配置方法,帮助提高应用程序性能。 8. **性能调优**:提供了关于如何优化Hibernate应用性能的一系列建议,包括查询优化、连接池配置等。 9. **集成测试**:介绍了...
7. **缓存机制**:介绍Hibernate的缓存层次,包括一级缓存(Session缓存)和二级缓存(SessionFactory缓存),以及第三方缓存插件如EhCache的集成。 8. **事务管理**:学习如何在Hibernate中处理事务,包括编程式...
达内教育作为国内知名的IT培训机构,也对此进行了深入的研究,并分享了其自创的Hibernate API设计与实现。本文将围绕“达内Hibernate自创API”这一主题,详细阐述其核心思想和关键特性。 一、理解Hibernate基础 在...