什么是缓存,为什么使用缓存的这些问题我就不再阐述了。
直接进入正题,hibernate分为一级缓存和二级缓存,这里主要说的是二级缓存。
从配置开始 src 下创建文件名为:ehcache.xml
<ehcache> <diskStore path="java.io.tmpdir"/> <defaultCache maxElementsInMemory="10000" eternal="false" overflowToDisk="true" timeToIdleSeconds="7200" timeToLiveSeconds="3600" diskPersistent="false" diskExpiryThreadIntervalSeconds="120" /> </ehcache>
hibernate.cfg.xml加上
<property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
<property name="hibernate.cache.use_query_cache">true</property>
在hibernate查询代码里加上query.setCacheable(true);
这时已经开启了二级缓存,具体细节不做具体描述,因为我写这个东西的本意是想记录下如果合理使用二级缓存。
当然我们知道hibernate里有两种方法获取一个列表数据分别为.iterator()和.list(),那么什么时候使用iterator什么时候使用list呢?
场景一:
获得数据库论坛板块信息,我们知道,数据库论坛板块的信息,基本上半年一年才变动一次,而且每次发送到数据库的sql语句,和返
回来的数据基本上都是一模一样的(也就是数据信息和sql语句(搜索条件)很少会修改的),那么这个时候我们应该考虑使用list方法来返回
信息,因为list方法第一次执行的时候会把数据库的数据信息都存放到二级缓存中,同时会记录你发送的sql语句,如果下次你还是利用
list方法发送一模一样的sql语句,同时数据也没有在被hibernate知道的情况下修改过,那么第二次甚至第n次再执行这个语句的时
候,hibernate是不用连接数据库的,而是直接把缓存里的数据返回给你。
场景二:
获得论坛某个板块的最新的20条信息,我们知道,论坛的第一页总是显示新发布或则有新回复的帖子,那么我们这个时候能使用list
方法来获取信息吗?答案是否定的。它虽然满足了list的条件之一(搜索条件很少会修改的),但是未满足另外一个条件,因为它数据信
息的修改是很频繁的(有新帖,或新回复的帖),那么这个时候我们就得考虑使用iterator来获取数据信息,iterator的原理是这样的,首先
先发送一条语句(iterator时query的sql:select * from table where id>n 真正发送:select id from table where id>n)获得所有符
合条件的ID,然后到二级缓存里边去找这个对象,如果发现,则获取它,如果没发现,则发送一条语句获得该ID的对象(n+1问题),比
方说,我们要获得最新20条信息(之前已经查询过一次,但现在有一个新帖),使用iterator方法会先发送一条语句获得满足SQL语句条
件的所有的ID,然后因为之前已经查询过一次,所以缓存里边已经有其中的19个帖子的缓存(因为有一个是新帖还没被hibernate查询
过,所以缓存里边还没有),然后再发送一条条件为ID=新帖ID的SQL语句来获得这个新帖的对象。
总结:
当hibernate二级缓存开启时,只要是经由hibernate的session对象来获得的任何对象hibernate都会把它放到缓存里
边,当该对象被修改或删除时,hibernate会把该对象在二级缓存中也删除掉。list方法一次获得所有数据同时放到缓存
中,如果SQL语句不变同时数据也没被改变的情况下,list直接取的缓存而不用再连接数据库进行检索操作,iterator方法用
n+1此来获得所有数据信息同时放到缓存中,不管SQL语句变没变始终会发送一条获得ID的SQL语句,然后根据ID查找缓
存,如果没有则再发送一条SQL语句获得该对象,虽然iterator始终会发送一条或(n+1)条,但发送的语句都是根据ID来获
取的,所以速度也是非常可观的(相对没有任何缓存机制而言)。
如果某个地方还没理解,或是我理解有误的地方还请指出,感谢。