二级缓存
与Session相对的是,SessionFactory也提供了相应的缓存机制。SessionFactory缓存可以依据功能和目的的不同而划分为内置缓存和外置缓存。
SessionFactory的内置缓存中存放了映射元数据和预定义SQL语句,映射元数据是映射文件中数据的副本,而预定义SQL语句是在Hibernate初始化阶段根据映射元数据推导出来的。SessionFactory的内置缓存是只读的,应用程序不能修改缓存中的映射元数据和预定义SQL语句,因此SessionFactory不需要进行内置缓存与映射文件的同步。SessionFactory的外置缓存是一个可配置的插件。在默认情况下,SessionFactory不会启用这个插件。外置缓存的数据是数据库数据的副本,外置缓存的介质可以是内存或者硬盘。SessionFactory的外置缓存也被称为Hibernate的二级缓存。Hibernate的二级缓存的实现原理与一级缓存是一样的,也是通过以ID为key的Map来实现对对象的缓存。由于Hibernate的二级缓存是作用在SessionFactory范围内的,因而它比一级缓存的范围更广,可以被所有的Session对象所共享二级缓存的实现原理:
从数据库里查询得到的类对象,根据这个类的id把它保存到一个map的集合里,这个id作为key,而这个对象实例作为value,而这个map的生命周期是sessionfactroy范围里的,这样,当我们想要从缓存里拿对象时,根据查询的id直接去map里拿对应的value(也就是对象实例)。
二级缓存的工作内容
1.在配置好二级缓存的情况下,包括指定那个类可以被保存到二级缓存里,这时从数据库里查询得到的类对象,hibernate将它保存到二级缓存里;
2.当hibernate根据Id 查询对象时,会先从一级缓存里找(也就是session里找),如果找不到并且配置了二级缓存,那么hibernate 会去二级缓存里找,如果还找不到,那么就根据id 直接查询数据库。
二级缓存的适用范围
适合于:
1.很少要修改的数据;这种即使并发也不怕
2.不并发的数据
如:某些数据是属于一个用户所有,那么这些数据放在二级缓存里,虽然是共享,但别人是不会使用到你的数据的,因为查询数据库使用的id 是不同的
不适合
1 经常被修改的数据。
2 财务数据,绝对不允许出现并发。
3 与其他应用共享的数据
二级缓存的配置
hibernate 默认关闭二级缓存的,要使用必须进行如下配置:
1. 、首先设置EhCache,建立配置文件ehcache.xml,默认的位置在class-path,可以放到你的src目录下:
<ehcache>
<diskStore path="java.io.tmpdir"/>
<defaultCache
maxElementsInMemory="10000"
eternal="false"
overflowToDisk="true"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
diskPersistent="false"
/>
</ehcache>
属性说明:
maxElementsInMemory属性用于指定缓存中最多可放多少个对象。
eternal属性指定缓存是否永久有效。
timeToIdleSeconds属性指定缓存多久未被使用便清理掉。
timeToLiveSeconds属性指定缓存的生命长度。
diskPersistent属性指定缓存是否被持久化到硬盘中,保存路径由<diskStore>标签指定。
2.修改hibernate.cfg.xml文件设置二级缓存。
<hibernate-configuration>
<session-factory>
<!-- 设置缓存提供者 -->
<property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
<mapping resource="cn/ineeke/entity/User.hbm.xml"/>
</session-factory>
</hibernate-configuration>
说明:可以通过设置hibernate.cache.provider_class属性,指定其他的缓存策略(也就是实现类),该缓存策略必须实现 org.hibernate.cache.CacheProvider接口。
通过实现org.hibernate.cache.CacheProvider接口可以提供不同二级缓存组件的支持
表14.1 Hibernate所支持的二级缓存组件
|
组件 |
Provider类 |
类型 |
集群 |
查询缓存 |
|
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 |
集群 |
支持 |
支持 |
3.指定哪些实体类会被保存到二级缓存。经过第二步缓存是启用了,但是并没有被使用。它不会去自动把所有的实体都进行缓存了,而是需要手动指定哪个实体需要缓存,以及其缓存的策略。
在User.hbm.xml中使用<cache>标签启用。
<hibernate-mapping>
<class name="cn.ineeke.entity.User" table="t_user">
<cache usage="read-only"/>
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
</class>
</hibernate-mapping>
注意:这里的<cache>标签一定要放在 <id >标签的前面
4. 到了这里hibernate只会缓存使用load()方法获得的单个持久化对象,如果想缓存使用list()、Iterator()、createCriteria()、createQuery()等方法获得的数据结果集的话,就需要在hibernate.cfg.xml添加
<property name="hibernate.cache.use_query_cache">true</property>
5.测试用例:
先在session里load()一个对象,接着关闭session用相同的id 再load()这个对象,第二次在控制台没有看到查询的sql语句
注意:
a.sessionfactroy的生命周期是在初始化后直到服务器关闭,
b.第一次load这个对象后,(这个对象在二级缓存里有限制存活多久的,在上面的<ehcache>里配置,)如果在这个时间内,那么直接可以拿到。
1万+

被折叠的 条评论
为什么被折叠?



