Hibernate缓存策略


title: Hibernate缓存策略
date: 2018-09-02 16:29:56
tags: [Hibernate, 缓存]
categories: Hibernate

一、什么是Hibernate一级缓存

1、 一级缓存范围

(1)Hibernate 一级缓存又称之为"Session 缓存"、“会话级缓存”
(2)通过Session从数据库查询时会吧实体在内存中存储起来,下一次查询同一实体时不再从数据库获取,而是从内存中获取,这就是缓存。
(3)一级缓存的生命周期和session相同;Session 销毁它也会销毁
(4)一级缓存中的数据可适用范围在当前会话之内

测试用例(1):
Hibernate缓存策略_第1张图片

2、 清理一级缓存

一级缓存无法取消,用两个方法管理。
(1)session.evict(obj) :会把指定的缓冲对象进行清除。
(2) session.clear() :把缓冲区内的全部对象清除,但不包括操作中的对象。

测试用例1session.evict(obj) 清理当前对象后,再次查询需要查询数据库:
Hibernate缓存策略_第2张图片

测试用例2 session.clear 后(需要从数据库中查询):
Hibernate缓存策略_第3张图片

3、一级缓存注意问题:

(1)query.list()是不会使用一级缓存的
(2)query.iterate()会使用一级缓存,当缓存中有数据的时候,query.iterate()将所有对象的id查询出来然后到缓存中将所有对象都查询出来,如果缓存中没有数据,query.iterate()则把对象从数据库中一条一条的将数据查出来
(3)一级缓存也有些时候会对程序的性能产生影响,因为在对数据库进行增删改的时候同时也要更新缓存

测试用例1 query.list 不会使用缓存:
Hibernate缓存策略_第4张图片

测试用例2 query.iterate()会使用一级缓存:
Hibernate缓存策略_第5张图片
我们看到,当如果通过iterator()方法来获得我们对象的时候,hibernate首先会发出1条sql去查询出所有对象的 id 值,当我们如果需要查询到某个对象的具体信息的时候,hibernate此时会根据查询出来的 id 值再发sql语句去从数据库中查询对象的信息,这就是典型的 N+1 的问题。

二、Hibernate二级缓存

1、 二级缓存简介

二级缓存的生命周期是SessionFactory,当SessionFactory关闭时,缓存才会清空.
二级缓存是每个session共用的缓存,并不是默认开启的,需要手动去配置.

Hibernate缓存策略_第6张图片

2 、二级缓存配置步骤

1.添加二级缓存对应的jar包.
jar包:commons-logging-1.1.3.jar、ehcache.jar

2.在Hibernate的配置文件中添加Provider类的描述(即添加二级缓存接口对应外部的实现类).
net.sf.ehcache.hibernate.EhCacheProvider

     
        <property name="hibernate.cache.use_second_level_cache">trueproperty>
        
        <property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactoryproperty>
        
        <property name="hibernate.cache.provider_configuration_file_resource_path">ehcache.xmlproperty>

3.添加二级缓存的属性配置文件,直接放在src根目录即可.
ehcache.xml

<ehcache>

    
  
  
    <diskStore path="user.dir"/>  

  
    
  
  

  
    <cache name="com.xiaoluo.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>

4.如果使用xml配置,我们需要在 Student.hbm.xml 中加上一下配置。在需要被缓存的表所对应的映射文件中添加标签.

配置文件配置

在标签下添加

<hibernate-mapping package="com.xiaoluo.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配置,我们需要在Student这个类上加上这样一个注解:

@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;
    .......
}

3、二级缓存注意事项

(1)二级缓存的使用策略一般有这几种:read-only、nonstrict-read-write、read-write、transactional。注意:我们通常使用二级缓存都是将其配置成 read-only ,即我们应当在那些不需要进行修改的实体类上使用二级缓存,否则如果对缓存进行读写的话,性能会变差,这样设置缓存就失去了意义。
(2)二级缓存缓存的仅仅是对象,如果查询出来的是对象的一些属性,则不会被加到缓存中去
(3)当我们如果通过 list() 去查询两次对象时,二级缓存虽然会缓存查询出来的对象,但是我们看到发出了两条相同的查询语句,这是因为二级缓存不会缓存我们的hql查询语句,要想解决这个问题,我们就要配置我们的查询缓存了。
(4)查询缓存(sessionFactory级别)

我们如果要配置查询缓存,只需要在hibernate.cfg.xml中加入一条配置即可:

     
        <property name="hibernate.cache.use_query_cache">trueproperty>

然后我们如果在查询hql语句时要使用查询缓存,就需要在查询语句后面设置这样一个方法:

List<Student> ls = session.createQuery("from Student where name like ?")
                    .setCacheable(true)  //开启查询缓存,查询缓存也是SessionFactory级别的缓存
                    .setParameter(0, "%王%")
                    .setFirstResult(0).setMaxResults(50).list();

如果是在annotation中,我们还需要在这个类上加上这样一个注解:@Cacheable

4、 二级缓存使用场景

Hibernate缓存策略_第7张图片

三、Hibernate一级、二级缓存的对比

Hibernate缓存策略_第8张图片

四、参考

https://www.cnblogs.com/xiaoluo501395377/p/3377604.html
https://www.imooc.com/learn/465

五、欢迎关注米宝窝,持续更新中,谢谢!

米宝窝 https://rocklei123.github.io/

你可能感兴趣的:(Hibernate)