1、 一级缓存(session)
hibernate一级缓存机制是session级别的,只要关闭session,则缓存清空,此时会再次发出sql查询数据库。
2、 二级缓存(sessionFactory)
使用hibernate二级缓存需要进行配置:
1.hibernate并没有提供相应的二级缓存的组件,所以需要加入额外的二级缓存包,常用的二级缓存包是EHcache。
porm.xml
<!-- https://mvnrepository.com/artifact/net.sf.ehcache/ehcache -->
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>2.10.1</version>
</dependency>
<!-- 开启二级缓存 -->
<property name="hibernate.cache.use_second_level_cache">true</property>
<!-- 二级缓存的提供类 在hibernate4.0版本以后我们都是配置这个属性来指定二级缓存的提供类-->
<property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
<!-- 二级缓存配置文件的位置 -->
<property name="hibernate.cache.provider_configuration_file_resource_path">ehcache.xml</property>
ehcache.xml
<ehcache>
<!-- Sets the path to the directory where cache .data files are created.
If the path is a Java System Property it is replaced by
its value in the running VM.
The following properties are translated:
user.home - User's home directory
user.dir - User's current working directory
java.io.tmpdir - Default temp file path -->
<!--指定二级缓存存放在磁盘上的位置-->
<diskStore path="user.dir"/>
<!--我们可以给每个实体类指定一个对应的缓存,如果没有匹配到该类,则使用这个默认的缓存配置-->
<defaultCache
maxElementsInMemory="10000"//在内存中存放的最大对象数
eternal="false"//是否永久保存缓存,设置成false
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"//如果对象数量超过内存中最大的数,是否将其保存到磁盘中,设置成true
maxElementsOnDisk="10000000"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU"
/>
<!--
1、timeToLiveSeconds的定义是:以创建时间为基准开始计算的超时时长;
2、timeToIdleSeconds的定义是:在创建时间和最近访问时间中取出离现在最近的时间作为基准计算的超时时长;
3、如果仅设置了timeToLiveSeconds,则该对象的超时时间=创建时间+timeToLiveSeconds,假设为A;
4、如果没设置timeToLiveSeconds,则该对象的超时时间=max(创建时间,最近访问时间)+timeToIdleSeconds,假设为B;
5、如果两者都设置了,则取出A、B最少的值,即min(A,B),表示只要有一个超时成立即算超时。
-->
<!--可以给每个实体类指定一个配置文件,通过name属性指定,要使用类的全名-->
<cache name="com.ssh.entity.Professional"
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
overflowToDisk="true"
/>
</ehcache>
开启二级缓存:
1)若使用xml配置,则需要在.hbm.xml文件中加上一句话:
<cache usage="read-only"/>
二级缓存的使用策略一般有这几种:read-only、nonstrict-read-write、read-write、transactional。 注意 :我们通常使用二级缓存都是将其配置成 read-only ,即我们应当在那些不需要进行修改的实体类上使用二级缓存,否则如果对缓存进行读写的话,性能会变差,这样设置缓存就失去了意义。
2)若使用注解方式,则需要加上:
@Cache(usage=CacheConcurrencyStrategy.READ_ONLY) // 表示开启二级缓存,并使用read-only策略
在配置了二级缓存以后,在session关闭后去查询对象的时候,此时hibernate首先会去二级缓存中查询是否有该对象,若有就不会再发sql了,但是二级缓存缓存的仅仅是对象,如果查询出来的是对象的一些属性,则不会被加到缓存中去。
3、 查询缓存(sessionFactory)
因为二级缓存不会缓存我们的hql查询语句,所以我们就要配置查询缓存来解决这个问题。
配置查询缓存,只需要在hibernate.cfg.xml中加入一条配置语句:
<!-- 开启查询缓存 -->
<property name="hibernate.cache.use_query_cache">true</property>
在查询语句后面设置这样一个方法:
Query query=session.createQuery(hql).setCacheable(true);
如果是在annotation中,则需要在类上加上注解:@Cacheable。
只有当 HQL 查询语句完全相同时,连参数设置都要相同,此时查询缓存才有效,而且使用查询缓存必须开启二级缓存。
hibernate 的查询缓存是主要是针对普通属性结果集的缓存, 而对于实体对象的结果集只缓存id。
在一级缓存,二级缓存和查询缓存都打开的情况下作查询操作时这样的:查询普通属性,会先到查询缓存中取,如果没有,则 查询数据库;查询实体,会先到查询缓存中取id,如果有,则根据id到缓存(一级/二级)中取实体,如果缓存中取不到实体,再查询数据库,此时查就是一个 N+1的效果。和一级/二级缓存不同,查询缓存的生命周期 ,是不确定的,当前关联的表发生改变时,查询缓存的生命周期结束)