首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

Hibernate二级缓存与查询缓存有关问题

2012-08-27 
Hibernate二级缓存与查询缓存问题http://www.sunxin.org/forum/thread/22597.html?page1由于对Hibernate

Hibernate二级缓存与查询缓存问题

http://www.sunxin.org/forum/thread/22597.html?page=1
由于对Hibernate的二级缓存和查询缓存的区别不了解,也不知道它们起什么作用。于是动手做了一些
实验,对它们的组合使用有了一个表面的认识。
1.前提
???????? 1) 不使用一级缓存(Session级别)的情况。因为大部分api对session的操作都进行n层封装,用
?
完session就close,一般很少使用到一级缓存。
?
???????? 2) 开启hibernate.show_sql=true,根据sql的是否输出来判断是否访问了数据库。
2.基础
2.1.二级缓存
???????? 二级缓存是SessionFactory级别的全局缓存,它为每个类(或集合)提供缓存。凡是调用二级缓
?
存的查询方法都会从中受益,比如load,list,iterate等方法(注意,get和find不使用缓存,直接访问数据
?
库)。
?
???????? 开启条件:
?
???????? 1)hibernate.cache.provider_class=org.hibernate.cache.EhCacheProvider(这里指定了ehcache)
?
???????? 2)hbm.xml配置<cache usage="read-write"/>
?
???????? 3)ehcache.xml定义该类的cache
?
???????? 简单地说,二级缓存是用来保存类对象的,并且填充它的所有属性值。
2.2.查询缓存
???????? 查询缓存保存的是查询方法(list和iterate等)查询的sql语句和结果集,跟load这种装载对象的方
?
法没有关系。也就是说,使用load方法,查询缓存不理睬。
?
???????? 并且这个结果集只是对象id列表,对象的其他属性值不保存。例如,list执行的时候,先根据查询
?
缓存中的sql语句,获取对象id列表,然后再load(id)来取对象。
?
???????? 开启条件:
?
???????? 1) hibernate.cache.use_query_cache=true
?
???????? 2)Query或者Criteria使用时,设置setCacheable(true)
?
???????? 简单地说,查询缓存是用来保存sql执行后获取的对象id列表。下一次执行同一条sql时,可直接从
?
查询缓存中获取到对象id列表。
3.实验
???????? 以下对最常用的load和list方法进行二级缓存和查询缓存的组合测试。load和list执行的结果,都是
?
返回同一个对象。
3.1.四种组合
???????? 二级缓存和查询缓存的组合,根据开启和不开启两种情况,划分为四种组合(√代表开启,×代
?
表不开启):
????????


??????????? 组合
????????????
??????????? 二级缓存
????????????
??????????? 查询缓存
????????????
??????????? 1
????????????
??????????? √
????????????
??????????? ×
????????????
??????????? 2
????????????
??????????? ×
????????????
??????????? √
????????????
??????????? 3
????????????
??????????? √
????????????
??????????? √
????????????
??????????? 4
????????????
??????????? ×
????????????
??????????? ×
????????????

3.2.load实验
???????? 对同一个id,使用load执行两次,观察sql的输出现象,也就是判断第二次load是否访问了数据
?
库。其中√代表输出,×代表未输出:
?


??????????? 组合
????????????
??????????? 第一次sql
????????????
??????????? 第二次sql
????????????
??????????? 结论
????????????
??????????? 1
????????????
??????????? √
????????????
??????????? ×
????????????
??????????? 与查询缓存无关
????????????
??????????? 2
????????????
??????????? √
????????????
??????????? √
????????????
??????????? 3
????????????
??????????? √
????????????
??????????? ×
????????????
??????????? 4
????????????
??????????? √
????????????
??????????? √
????????????

?
???????? 当开启了二级缓存,load先从缓存中获取对象,于是组合1和3的第二次sql都未输出,即第二次查
?
询没有访问数据库。
?
???????? 当没有开启二级缓存,load总是直接访问数据库的。也证明了,查询缓存与load方法无关。
3.3.list实验
???????? 对同一条sql语句,使用list执行两次,观察sql的输出现象。其中√代表输出,×代表未输出:
?


??????????? 组合
????????????
??????????? 第一次sql
????????????
??????????? 第二次sql
????????????
??????????? 结论
????????????
??????????? 1
????????????
??????????? √
????????????
??????????? √
????????????
??????????? list每次访问数据库都会填充二级缓存,相当于二级缓存无效
????????????
??????????? 2
????????????
??????????? √
????????????
??????????? √(不一样)
????????????
??????????? 这两条sql语句不一样,第一条是list的,第二条是load的
????????????
??????????? 3
????????????
??????????? √
????????????
??????????? ×
????????????
????????????
????????????
??????????? 4
????????????
??????????? √
????????????
??????????? √
????????????
????????????
????????????

?
???????? 对组合1现象的解释:
???????? 当没有开启查询缓存时,list每次都会直接访问数据库,然后把二级缓存给重新填充。也就是说,
?
list在不开启查询缓存的情况下,根本就没有利用到二级缓存的好处。
?
???????? 对组合2现象的解释:
?
???????? 第一条sql是list正常访问数据库的,但第二次执行list时,由于有了查询缓存,直接根据第一条sql
?
获取对象的id,此时由于没有开启二级缓存,load(id)后也没法从二级缓存中拿数据,只好再次访问数
?
据库。但在组合3中,load(id)可以从二级缓存中拿数据,所以不用访问数据库。
3.4.小结
???????? 在load和list方法中,使用二级缓存和查询缓存的不同组合,效果出现了差别。特别强调的是,由
?
于很多操作是基于list的,如果没有开启查询缓存,根本就使用不了二级缓存的数据,也就提高不了性
?
能了(但是iterate可以使用到二级缓存)。
?
???????? 另外,从表格中可以看出来,同时开启二级缓存和查询缓存,效果是最好的,第二次查询都不需
?
要访问数据库。
4.维护
???????? 当存在除hibernate之外的改变数据库数据的方式时,维护二级缓存和查询缓存是很麻烦的。比如
?
使用jdbc或者第三方系统修改了数据库,hibernate都不知道,也就没法自行维护缓存了。这时需要手
?
动维护,如果存在第三方系统,还需要让第三方系统发消息通知hibernate。
?
???????? 维护手段也就是evict(清除某个类的二级缓存)和evictQuery(清除查询缓存)。针对数据修改
?
的三种形式,分别维护:
???????? 1)insert:evictQuery
???????? 2)delete:evict和evictQuery
???????? 3)update:evict

热点排行