Hibernate缓存概述
1、Hibernate缓存概述
缓存是介于物理数据源与应用程序之间,是数据库数据在内存中的存放临时copy的容器,
其作用是为了减少应用程序对物理数据源访问的次数,从而提高了应用的运行性能。
Hibernate在进行读取数据的时候,根据缓存机制在相应的缓存中查询,
如果在缓存中找到了需要的数据(我们把这称做“缓存命中"),则就直接把命中的数据作为结果加以利用,
避免了建立数据库查询的性能损耗。
2:Hibernate缓存分类
一级缓存(session):内部缓存
事务范围:缓存只能被当前事务访问。缓存的生命周期依赖于事务的生命周期,
当事务结束时,缓存也就结束生命周期。
二级缓存(sessionFactory):缓存被应用范围内的所有事务共享。
这些事务有可能是并发访问缓存,因此必须对缓存进行更新。
缓存的生命周期依赖于应用的生命周期,应用结束时,
缓存也就结束了生命周期,二级缓存存在于应用范围。
集群范围:在集群环境中,缓存被一个机器或者多个机器的进程共享。
缓存中的数据被复制到集群环境中的每个进程节点,
进程间通过远程通信来保证缓存中的数据的一致性,
缓存中的数据通常采用对象的松散数据形式,二级缓存也存在与应用范围。
注意:对大多数应用来说,应该慎重地考虑是否需要使用集群范围的缓存,
再加上集群范围还有数据同步的问题,所以应当慎用。
多种范围的缓存处理过程
持久化层可以提供多种范围的缓存。如果在事务范围的缓存中没有查到相应的数据,
还可以到应用范围或集群范围的缓存内查询,如果还是没有查到,那么只有到数据库中查询了。
缓存应用的范围:
修改少,数量在可以接受的范围内
5、使用二级缓存的原则:
数据不会被第三方修改
同一数据系统经常引用
数据大小在可接受范围之内
关键数据或不会被并发更新的数据
5、hibernate引入第三方的缓存组件EHCACHE,下面是具体的实现步骤:\
修改hibernate.cfg.xml配置引入ehCache缓存
<hibernate-configuration>
<session-factory>
<propertyname="hibernate.cache.provider_class">
net.sf.ehcache.hibernate.EhCacheProvider
</property>
<!--query也支持缓存-->
<propertyname="hibernate.cache.use_query_cache">true</property>
</session-factory>
</hibernate-configuration>
在src根目录下加入ehcache.xml文件,具体内容如下:
<ehcachexmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:noNamespaceSchemaLocation="ehcache.xsd">
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
/>
</ehcache>
在映射文件中指定缓存同步策略
<classname="com.tenly.bean.Student">
<cacheusage="read-write">
<setname="classroom">
<cacheusage="read-only">
</set>
</class>
usage属性说明:
read-only:只读。对于不会发生改变的数据,可使用只读型缓存。
nonstrict-read-write:不严格可读写缓存。如果应用程序对并发访问下的数据同步要求不是很严格的话,
而且数据更新操作频率较低。采用本项,可获得良好的性能。
read-write
对于经常被读但很少修改的数据,可以采用这种隔离类型,因为它可以防止脏读这类的并发问题.
transactional(事物型)
在Hibernate中,事务型缓存必须运行在JTA事务环境中。
在测试query时,说明其将用二级缓存
query.setCacheable(true);
3、释放缓存:
一级缓存的释放
Session.evict(XXX)
将某个特定的对象从内部缓存中清除,上述的XXX为对象的实例名。使用此方法有两种适用情形,
需要及时释放对象占用的内存维持系统的稳定性
是不希望当前Session继续运用此对象的状态变化来同步更新数据库。
Session.clear()清除所有的一级缓存
二级缓存的释放
SessionFacatoyr.evict(XXX)
将某个特定的对象从内部缓存中清除,上述的XXX为对象的实例名。使用此方法有两种适用情形,
需要及时释放对象占用的内存维持系统的稳定性
是不希望当前Session继续运用此对象的状态变化来同步更新数据库。
SessionFactory.clear()清除所有的二级缓存
6、查询缓存:
二级缓存策略的一般过程:
Hibernate进行条件查询的时候,总是发出一条select*fromXXXwhere…(XXX为表名,
类似的语句下文统称SelectSQL)这样的SQL语句查询数据库,一次获得所有的符合条件的数据对象。
把获得的所有数据对象根据ID放入到第二级缓存中。
当Hibernate根据ID访问数据对象的时候,首先从内部缓存中查找,如果在内部缓存中查不到就配置二级缓存,
从二级缓存中查;如果还查不到,再查询数据库,把结果按照ID放入到缓存。
添加数据、删除、更新操作时,同时更新二级缓存。这就是Hibernate做批处理的时候效率不高的原因,
原来是要维护二级缓存消耗大量时间的缘故。
条件查询的处理过程:
第一次查找age>20的所有学生信息,然后纳入二级缓存。
第二次我们的查询条件变了,查找age>15的所有学生信息,显然第一次查询的结果完全满足第二次查询的条件,
但并不是满足条件的全部数据。这样的话,我们就要再做一次查询得到全部数据才行。
如果我们执行的是相同的条件语句,Hibernate引入QueryCache的。
查询缓存策略的一般过程:
完全相同的SelectSQL重复执行。
重复执行期间,QueryKey对应的数据表不能有数据变动(比如添、删、改操作)
启用QueryCache,我们需要在hibernate.cfg.xml中进行配置,参考配置如下(只列出核心配置项):
<hibernate-configuration>
<session-factory>
<propertyname="hibernate.cache.user_query_cache">true</property>
</session-factory>
</hibernate-configuration>
在查询执行之前,将Query.Cacheable设置为true,而且每次都应该这样。比如:
Queryquery=session.createQuery(hql).setInteger(0.15);
query.setCacheable(true);