`
huangjian325
  • 浏览: 6301 次
  • 性别: Icon_minigender_1
  • 来自: 南宁
文章分类
社区版块
存档分类
最新评论

详解hibernate的缓存机制,不理解缓存的童鞋就来看看吧……

阅读更多

如果你还在为理解hibernate的缓存机制而去查阅大量的资料,然后看这些资料你又觉得头疼,那就可以看看我的这篇文章了,如果你觉得看别的资料,对你的理解起到更大的作用,那就不要看我的这篇了……本人写的文章都是以一种简单易懂的原则去写的,要是你觉得你的理解能力够强大,那可以去看更专业的文章,不过我的每一篇文章都是原创,适合广大新手程序员学习,因为我也算是新手啦,要是想看我的更多原创文章,上我的社区博客吧……

 

首先说一下Hibernate的缓存一般有两种,一级缓存、二级缓存(还有一个特别的缓存:查询缓存)

 

一级缓存

         一级缓存也叫做session缓存,它是hibernate的内置缓存,不能被卸载,并且每个session对应自己的缓存,不能跨越session进行该级别的缓存。

 

举例说明问题吧:

          在一个sessionload一个对象,并且打印它的属性,那么在打印的时候会发出一跳数据库查询语句,假如此时我又在该session里又load了同一个对象(id相同),那么我再打印这个对象的属性的时候,hibernate就不会再发出数据库查询语句了,直接从session缓存中读取,这就是一级缓存。

         为了说明一级缓存的不可跨越性,我们来考虑下面一个问题,如果我们在两个不同的sessionload同一个对象会是什么情况呢?假若我们在session1load数据库id1的对象,并打印其属性,hibernate会发出一条数据库查询语句;我们又在session2load同样id1的对象,并打印其属性,此时hibernate又发出了同样的一条查询语句,那么这就可以证明,hibernate的一级缓存的确为session级别的缓存,它是不可跨越session的。

         但是这个一级缓存存在一些可考量的问题,假若我们load id1的对象的操作是分布在多个不同的线程里的,那么是不是我们每次load这个对象,都要发出一条数据库查询语句?当然会,因为不同线程里的session是不同的,每一次load对象当然就会再发出一跳查询语句,这样就带来一些性能上的问题,那么要怎么解决这个性能上问题?我们可以将问题简单化,我们可以这样思考:我们怎么做才可以让不同的session去获取同一个缓存里的东西呢?解决方案就是接下来要说的二级缓存……

 

二级缓存

         注:使用load方法加载对象,默认是先从二级缓存里查找,二级缓存没有,才回去数据库里查找

         二级缓存也叫SessionFactory级别的缓存,它是可以跨越session存在的。还是用上面所遇到的问题来解释学习二级缓存的概念,画一个图来说明我们怎么解决上面所遇到的性能问题,图中的session1session2都要load一个id1的对象,那么在加入了二级缓存的机制之后,这个load就变成如图所示的过程



 释一下这个过程,两个sessionload用一个对象,它们会先去二级缓存里边找,如果找不到,才写查询语句去数据库里边拿。

下面就来深入的了解一下这个二级缓存的问题,首先说一下,hibernate早期自己实现了一个二级缓存,但是这个二级缓存只适用于程序的开发阶段,到hibernate3.2以后,它又实现了一个名字叫做EHCache的缓存实现,这个是3.2默认的二级缓存的实现。当然,除了hibernate自身实现的之外,还有很多厂商为其写了各自的二级缓存的实现,每一种都有各自的特点和使用价值。要使用哪种实现,你得要考虑,你的这个二级缓存的地址在哪里?是在内存里呢?还是在硬盘里?当对象太多之后,内存往往就就缓存不下了,那么我们就可以选择将对象缓存在硬盘上,要知道,从硬盘上获取对象,也要比从数据库中获取对象要来得更快。好了,当你决定了你的二级缓存要缓存的位置之后,你就可以考虑使用哪一个实现了,hibernate3.2EHCache,是可以缓存在内存里和硬盘里的。(别的实现,自己查阅文档!不懂文档在哪里……程序员不懂查阅原始文档,那就早点改行算了……)


 

上面说了要怎么选择二级缓存的实现,下面还有一个问题,我们在什么情况下才需要使用二级缓存,也许你会问,不就是上面解释一级缓存所说的那个性能问题的请况下吗?当然不是,使用不使用二级缓存,还有别的决定因素,这个决定因素不算很重要,你只要知道,一般情况下,我们都不需要使用二级缓存,等到必要要用的时候再去查找怎么实现就可以了,所以我个人觉得,如果不理解二级缓存,也不会写二级缓存,也没问题,事实证明,它并不常用,就算要用,其配置也相对简单。

 

 

 

二级缓存-查询缓存

什么情况下我们要考虑使用查询缓存呢?最直接的情况就是我们使用查询语句去查询数据库的时候,就可以考虑要不要使用查询缓存。

 

那什么样的查询情况下要考虑使用查询缓存呢?

举个例子:假如我们有一个查询语句叫“from User”,这个查询语句要多次的使用,那么我们就可以考虑每次使用这个查询语句的时候使用查询缓存了。


好了,hibernate的缓存机制其实就这么简单,最重要的还是一级缓存,因为一级缓存是我们经常遇到的,至于二级缓存,你觉得你要试试看怎么用,那就自己去做一下实验吧,很简单!而查询缓存,我个人举得还是经常会用到的,因为我们的项目里也会存在某个查询语句老是经常使用的情况,那你就可以考虑用查询缓存了!

 

这里我还是送上查询缓存的配置方法吧!

要使用查询缓存,得要有二级缓存的配置的前提下才可以使用,也就是说查询缓存是完全依赖于二级缓存的,二级缓存的配置我就不说了,直接奉上查询缓存的hibernate.cfg.xml里的配置,要在xml里加这么一句话

<property name="">true</property>

就是打开查询缓存的意思,有了这句话,你就可以在程序里写查询语句的时候加一个setCacheable(true),马上OK!

 

List blogs = sess.createQuery("from User")
    .setCacheable(true)
    .list();

 这样,当你经过了第一次使用之后,以后你每查询同样的hql语句,都setCacheable(true)一下,OK!这个查询缓存也是跨session级别的,这个应该显而易见了,因为它就是在二级缓存下的特例嘛!

程序缓存涉及的范围非常的广,当然也不只局限于hibernate的缓存,不过只要你能很好的理解了hibernate的缓存,那么其他的ORM框架的缓存机制,甚至操作系统的缓存机制,也都大大同小小异而已啦!

 

最后,祝你学习愉快!!!!!!!!!!

  • 大小: 16.4 KB
1
1
分享到:
评论
1 楼 wukele 2011-05-30  
 

相关推荐

Global site tag (gtag.js) - Google Analytics