Hibernate默认开启一级缓存,一级缓存级别是session
一级缓存特点:
(1)一级缓存使用范围session对象范围,session创建,分配区域作为一级缓存,同时为每个一级缓存作为快照区
(2)调用get方法时候,首先到一级缓存中找是否有相同数据,如果没有查询数据库,把查询出来持久态对象,放到一级缓存中
(3)修改持久态对象里面值,同时修改一级缓存中对应数据值,但是只会修改一级缓存值,不会修改快照区内容
(4)提交事务之前,做比较,比较一级缓存中内容和快照区内容是否一样,如果不一样把一级缓存中更新到数据库,如果一样,不更新
二级缓存(sessionFactory级别):
在hibernate.cfg.xml配置二级缓存
<!-- 开启二级缓存 -->
<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>
<!--这个类在4.0版本以后已经不建议被使用了,用于4.0之前的版本
<property name="hibernate.cache.provider_class">net.sf.ehcache.hibernate.EhCacheProvider</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
/>
<!--
1、timeToLiveSeconds的定义是:以创建时间为基准开始计算的超时时长;
2、timeToIdleSeconds的定义是:在创建时间和最近访问时间中取出离现在最近的时间作为基准计算的超时时长;
3、如果仅设置了timeToLiveSeconds,则该对象的超时时间=创建时间+timeToLiveSeconds,假设为A;
4、如果没设置timeToLiveSeconds,则该对象的超时时间=max(创建时间,最近访问时间)+timeToIdleSeconds,假设为B;
5、如果两者都设置了,则取出A、B最少的值,即min(A,B),表示只要有一个超时成立即算超时。
-->
<!--可以给每个实体类指定一个配置文件,通过name属性指定,要使用类的全名-->
<cache name="com.bean.Student"
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
overflowToDisk="true"
/>
<cache name="sampleCache2"
maxElementsInMemory="1000"
eternal="true"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
/> -->
</ehcache>
开启二级缓存:
如果是xml形式,需要在对应的实体类的xml文件中配置:
<hibernate-mapping package="com.bean">
<class name="Student" table="t_student">
<!-- 二级缓存一般设置为只读的 -->
<cache usage="read-only"/>
<id name="id" type="int" column="id">
<generator class="native"/>
</id>
<property name="name" column="name" type="string"></property>
<property name="sex" column="sex" type="string"></property>
<many-to-one name="room" column="rid" fetch="join"></many-to-one>
</class>
</hibernate-mapping>
如果使用annotation配置,我们需要在实体类上加上这样一个注解:
@Entity
@Table(name="t_student")
@Cache(usage=CacheConcurrencyStrategy.READ_ONLY) // 表示开启二级缓存,并使用read-only策略
public class Student
{
private int id;
private String name;
private String sex;
private Classroom room;
.......
}
二级缓存缓存的仅仅是对象,如果查询出来的是对象的一些属性,则不会被加到缓存中去
二级缓存会缓存 hql 语句:
xml配置方式需要在hibernate.cfg.xml中加入配置
<!-- 开启查询缓存 -->
<property name="hibernate.cache.use_query_cache">true</property>
然后我们如果在查询hql语句时要使用查询缓存,就需要在查询语句后面设置这样一个方法:
List<Student> ls = session.createQuery("from Student where name like ?")
.setCacheable(true) //开启查询缓存,查询缓存也是SessionFactory级别的缓存
.setParameter(0, "%王%")
.setFirstResult(0).setMaxResults(50).list();
annotation方式我们需要在这个类上加上这样一个注解:@Cacheable
只有当 HQL 查询语句完全相同时,连参数设置都要相同,此时查询缓存才有效