Hibernate缓存机制

一级缓存(session级别):如果再次请求同一方法,会首先去缓存中查看是否存在,不存在再去数据库查询,一级缓存是session级别的,如果session关闭之后就没有了,它是属于线程范围的缓存。这一级别的缓存由 hibernate 管理的,我们无需干预

session缓存的作用?
          * 减少数据库的访问频率,提高访问性能
          * 保证缓存中的对象与数据库同步,位于缓存中的对象称为持久化对象

一级缓存指的是session对象内部的一个HashMap  (session的实现类是:SessionImpl)
用户不需要做任何配置就可以使用,但它的生命周期非常小, 只要session关闭,缓存就消失
每个session拥有自己的缓存区, 执行session.save()操作的时候,会先放入一级缓存
--> 放入一级缓存的对象称为持久化对象

* 执行查询的时候,会先到session的一级缓存中查找 
          * 如果找到,直接从缓存中获取该对象,这时不再查询数据库
          * 如果没有找到,此时查询数据库,产生select语句,并把查询到的对象放入缓存
Customer c1 = (Customer) session.get(Customer.class, 1);

* 执行查询的时候,会将查到的对象放到session的一级缓存中一份,同时在session的快照中有一份复制
          当执行session.close()的时候,清理缓存,这时会比对缓存中对象的属性值和快照中对象的属性值,看是否一致
* 如果一致,不再执行update语句
* 如果不一致,执行update语句
* session如何判断持久化对象的状态发生改变呢?
* session加载对戏那个后会为对象属性复制一份快照,当session清理缓存时,会比较当前对象和它的快照就可以知道哪些属性发生了改变

* 在什么时候session会清理缓存呢?
          * 当应用程序调用Transaction的commit()方法时,该方法先清理缓存,然后向数据库提交事务
          * 当应用程序执行一些查询操作,如果缓存中持久化对象的属性已经发生了变化,会先清理缓存,以保证查询结果能反应持久化对象的最新状态
          * 显式的调用Session的flush()方法

注意: 清理缓存,缓存中的数据不会丢失,清理不等于清除  session.clear()为清空缓存
session.refresh(customer) 刷新数据库中的数据和缓存中的同步,方向: 从数据库-->缓存
session.fresh() 刷新session的一级缓存中的数据到数据库,让缓存中的数据跟数据库同步,方向: 从缓存--> 数据库
session在清理缓存时,会根据持久化对象的属性变化,来同步更新数据库

二级缓存(sessionFactory级别):

第一步:导jar包echace.jar.
第二部: 先使用ehcache-1.5.0.jar该缓存的默认配置,此时执行的是jar包下的ehcache-failsafe.xml文件
第三步:开启二级缓存,配置缓存提供的供应商,并将需要支持二级缓存的类配置到hibernte.cfg.xml中.
第四步:配置ehcache自己的配置文件:classpath:ehcache.xml (针对某个对象设置缓存)
第五步:配置一些信息,如:最多存多少个数据对象,数据对像太多时,不用的对象是否应该保存到硬盘上去

要使用二级缓存,还需要引入两个jar包(spring包下)
..\lib\concurrent\backport-util-concurrent.jar
..\lib\commons-logging.jar

Hibernate.cfg.xml:
<!-- 以下配置二级缓存-以下启动了二级缓存,默认是不开启的-->
    <property name="cache.use_second_level_cache">true</property>
    <property name="hibernate.cache.provider_class">
        org.hibernate.cache.EhCacheProvider
    </property>
    <!-- 以下打开查询缓存 -->
    <property name="hibernate.cache.use_query_cache">true</property>
    
    <!-- 打开二级缓存的统计信息
        hit:命中次数:是指从二级缓存中获取到了几次数据。
        miss:没有命中的次数。
     -->
<property name="hibernate.generate_statistics">true</property>
    <!--配置二级缓存中存放的数据类型,要放置在mapping元素的下面-->
<!--配置类级别的二级缓存-->
<class-cache class=”cn.itcast.Customer” usage=”read-write”/>
<class-cache class=”cn.itcast.Order” usage=”read-write”/>
<!--配置集合级别的二级缓存-->
<collection-cache class=”cn.itcast.Customer.orders” usage=”read-write”/>
也可以在映射文件里面配置(不推荐)
<class name=”cn.itcast.Customer” table=”customers”>
        <!--配置类级别的二级缓存,此时二级缓存中能存放Customer对象-->
        <cache usage=”read-write”/>   
        <id name=”id” type=”integer”>
        </id>
        ...
        <set name=”orders” table=”orders” inverse=”true”>
        <!—配置集合级别的二级缓存,此时orderes订单集合放入到二级缓存中-->
            <cache usage=”read-write”/>  
        </set>
</class>
eacache.xml
<ehcache>
    <!-- 设置当内存数据太多时,保存到哪一个目录 -->
    <diskStore path="d:/a"/>
    <!--以下是默认缓存区,必须存在
        eternal:在内存中的数据是否永不过期。建议设置为false
        -->
    <defaultCache
        maxElementsInMemory="100"
        eternal="false"
        timeToIdleSeconds="120"
        timeToLiveSeconds="300"
        overflowToDisk="true"
        />
    <!-- 以下定义一个有名的cache区 -->
    <cache name="itcast"
        maxElementsInMemory="100"
        eternal="false"
        timeToIdleSeconds="300"
        timeToLiveSeconds="600"
        overflowToDisk="true"
        />
</ehcache>
辅助理解一级缓存:
// 核心类,维护了一个map,相当于一个缓存
public class Baidu {
    private static Map<String,City> citys = new HashMap<String,City>();
    public static City getCity(String name){
        City city = citys.get(name);
        if(city==null){
            city = new City(name);
            citys.put(name, city);
        }
        return city;
    }
}
// 一个javabean,封装了城市的信息
public class City {
    private String name;
    public City(String name) {
        this.name = name;
    }
    ...
}
// 测试类
public class Main {
    public static void main(String[] args) {
        City city1 = Baidu.getCity("Beijing");   // 第一次获取北京的信息 -> 查缓存 -> 没有 -> 查数据库 -> 维护到缓存
        City city2 = Baidu.getCity("Beijing");   // 第二次查缓存 -> 有 -> 直接从缓存获取
        System.out.println(city1==city2);
    }
}
ehcache.xml配置说明

diskStore :缓存数据文件的存储目录

defaultCache 存储默认数据过期策略

cache: 设置具体的命名缓存的过期策略

name=“com.xxx.bean.Student” 使用类的全名为其指定缓存

maxElementsInMermory 属性设置缓存对象的最大数目

eternal 属性指定是否永不过期,true为不过期

timeToldelSeconds 属性设置对象处于空闲的最大秒数

timeToLiveSeconds 属性设置对象处于缓存状态的最大秒数

overforToDisk属性设置内存溢出时是否将溢出对象写入硬盘

在使用实体添加相关注解

@Cache(usage=CacheConCurrencyStrategy.Read_WRITE)

 

https://www.cnblogs.com/tianyuchen/p/6305657.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值