• 缓存


    mybatis提供一级缓存和二级缓存

    • mybatis一级缓存是一个SqlSession级别,sqlsession只能访问自己的一级缓存的数据

    • 二级缓存是跨sqlSession,是mapper级别的缓存,对于mapper级别的缓存不同的sqlsession是可以共享的。

    一级缓存

    第一次发出一个查询sql,sql查询结果写入sqlsession的一级缓存中,缓存使用的数据结构是一个map

    • key:hashcode+sql+sql输入参数+输出参数(sql的唯一标识)

    • value:用户信息

    • 第一次查询,把查询结果存到一个map中;第二次以相同sql查询,直接从缓存(map)中获取结果,即两次查询结果都是同一个Java对象,内存地址相同

    同一个sqlsession再次发出相同的sql,就从缓存中取不走数据库。如果两次中间出现commit操作(修改、添加、删除)或清除缓存(sqlSession.clearCache()),本sqlsession中的一级缓存区域全部清空,下次再去缓存中查询不到所以要从数据库查询,从数据库查询到再写入缓存。

    Mybatis一级缓存值得注意的地方:

    • Mybatis默认就是支持一级缓存的,并不需要我们配置.

    • mybatis和spring整合后进行mapper代理开发,不支持一级缓存,mybatis和spring整合,spring按照mapper的模板去生成mapper代理对象,模板中在最后统一关闭sqlsession

    一级缓存创建:在执行SQL语句时

    一级缓存保存:sqlSession.commit()sqlSession.close()

    一级缓存清除:sqlSession.clearCache(),增、删、改操作

    二级缓存

    二级缓存的范围是mapper级别(mapper同一个命名空间,多个sqlSession可以共享缓存),mapper以命名空间为单位创建缓存数据结构,结构是map。

    img

    二级缓存配置

    • 1、mybatis配置文件配置

    需要我们在Mybatis的配置文件中配置二级缓存

        <!-- 全局配置参数 -->
        <settings>
            <!-- 开启二级缓存 -->
            <setting city="cacheEnabled" value="true"/>
        </settings>
    • 2、映射文件Mapper.xml配置

    二级缓存的范围是mapper级别的,因此我们的Mapper如果要使用二级缓存,还需要在对应的映射文件中配置..

        <cache/>

    cache 标签属性

    • eviction : 缓存回收策略,有这几种回收策略(默认是 LRU 最近最少回收策略)

      • LRU - 最近最少回收,移除最长时间不被使用的对象

      • FIFO - 先进先出,按照缓存进入的顺序来移除它们

      • SOFT - 软引用,移除基于垃圾回收器状态和软引用规则的对象

      • WEAK - 弱引用,更积极的移除基于垃圾收集器和弱引用规则的对象

    • flushinterval 缓存刷新间隔,缓存多长时间刷新一次,默认不清空,设置一个毫秒值

    • readOnly: 是否只读;true 只读,MyBatis 认为所有从缓存中获取数据的操作都是只读操作,不会修改数据。MyBatis 为了加快获取数据,直接就会将数据在缓存中的引用交给用户。不安全,速度快。读写(默认):MyBatis 觉得数据可能会被修改

    • size : 缓存存放多少个元素

    • type: 指定自定义缓存的全类名(实现Cache 接口即可)

    • blocking: 若缓存中找不到对应的key,是否会一直blocking,直到有对应的数据进入缓存。

    • 3、POJO序列化

    mybatis二级缓存需要将查询结果映射的pojo实现 java.io.serializable接口,如果不实现则抛出异常:

    org.apache.ibatis.cache.CacheException: Error serializing object.  Cause: java.io.NotSerializableException: cn.itcast.mybatis.po.User

    二级缓存可以将内存的数据写到磁盘,存在对象的序列化和反序列化,所以要实现java.io.serializable接口。 如果结果映射的pojo中还包括了pojo,都要实现java.io.serializable接口。

    二级缓存失效

    • 第一次sqlSession未提交,SQL 语句产生的查询结果还没有放入二级缓存

    • 增、删、改 操作

    二级缓存源码

    • 二级缓存创建

      • 二级缓存的创建是使用 Resource 读取 mybatis的XML 配置文件开始的,读取配置文件后,需要对XML创建 Configuration并初始化

      • 根据配置文件中的<mapper>标签,去找对应的映射文件(namespace)

      • 找映射文件中的<cache>等与二级缓存相关的标签(看这个namespace是否开启二级缓存),再找sql语句标签

    二级缓存注意事项

    1. 缓存是以namespace为单位的,不同namespace下的操作互不影响。

    2. insert,update,delete操作会清空所在namespace下的全部缓存。

    3. 通常使用MyBatis Generator生成的代码中,都是各个表独立的,每个表都有自己的namespace

    4. 多表操作一定不要使用二级缓存,因为多表操作进行更新操作,一定会产生脏数据

    如果不能使用多表操作,二级缓存不就可以用一级缓存来替换掉吗?而且二级缓存是表级缓存,开销大,没有一级缓存直接使用 HashMap 来存储的效率更高,所以二级缓存并不推荐使用

    禁用二级缓存

    对于变化频率较高的sql,需要禁用二级缓存:

    在statement中设置useCache=false可以禁用当前select语句的二级缓存,即每次查询都会发出sql去查询,默认情况是true,即该sql使用二级缓存。

    <select id="findOrderListResultMap" resultMap="ordersUserMap" useCache="false">

    对查询频率高,变化频率低的数据建议使用二级缓存。

    对于访问多的查询请求且用户对查询结果实时性要求不高,此时可采用mybatis二级缓存技术降低数据库访问量,提高访问速度

    业务场景比如:

    • 耗时较高的统计分析sql、

    • 电话账单查询sql等。

    实现方法如下:通过设置刷新间隔时间,由mybatis每隔一段时间自动清空缓存,根据数据变化频率设置缓存刷新间隔flushInterval,比如设置为30分钟、60分钟、24小时等,根据需求而定。

     

  • 相关阅读:
    JavaScript中DOM的层次节点(一)
    JS可维护性代码
    Angular页面加载闪现解决方案 ng-cloak
    无法向会话状态服务器发出会话状态请求。
    算法题--拓扑排序
    2020年04月25日个人赛
    Educational Codeforces Round 86 (Rated for Div. 2)
    博弈--巴什博弈
    2020年04月19日个人赛
    AtCoder Beginner Contest 163(D)
  • 原文地址:https://www.cnblogs.com/yjh1995/p/13893766.html
Copyright © 2020-2023  润新知