zoukankan      html  css  js  c++  java
  • 分享知识-快乐自己:Mybatis缓存机制

    论缓存机制:

    1):mybatis 提供了缓存机制减轻数据库压力,提高数据库性能。
    2):mybatis 的缓存分为两级:一级缓存、二级缓存
    3):一级缓存是SqlSession级别的缓存,缓存的数据只在SqlSession内有效。
    4):二级缓存是mapper级别的缓存,同一个namespace公用这一个缓存,所以对SqlSession是共享的

    一级缓存:

    mybatis 的一级缓存是SqlSession级别的缓存,在操作数据库的时候需要先创建SqlSession会话对象,在对象中有一个HashMap用于存储缓存数据,此HashMap是当前会话对象私有的,别的SqlSession会话对象无法访问。

    具体流程:

    1).第一次执行select完毕会将查到的数据写入SqlSession内的HashMap中缓存起来
    2).第二次执行select会从缓存中查数据,如果select相同切传参数一样,那么就能从缓存中返回数据,不用去数据库了,从而提高了效率
     
    注意事项:
    1):一级缓存的作用域是SqlSession范围的,当在同一个SqlSession中执行两次相同的 sql 语句时,第一次执行完毕会将数据库中查询的数据写到缓存(内存)中,
      第二次查询时会从缓存中获取数据,不再去底层进行数据库查询,从而提高了查询效率。需要注意的是:如果SqlSession执行了DML操作(insert、update、delete),
      并执行commit()操作,mybatis则会清空SqlSession中的一级缓存,这样做的目的是为了保证缓存数据中存储的是最新的信息,避免出现脏读现象。
     
    2):当一个SqlSession结束后那么他里面的一级缓存也就不存在了,mybatis默认是开启一级缓存,不需要配置
     
    3):mybatis的缓存是基于[namespace:sql语句:参数]来进行缓存的,意思就是,SqlSession的HashMap存储缓存数据时,是使用[namespace:sql:参数]作为key,查询返回的语句作为value保存的。
     
    例:-1242243203:1146242777:winclpt.bean.userMapper.getUser:0:2147483647:select * from user where id=?:19

    二级缓存:

    二级缓存是mapper级别的缓存,也就是同一个namespace的mappe.xml,当多个SqlSession使用同一个Mapper操作数据库的时候,得到的数据会缓存在同一个二级缓存区域,二级缓存默认是没有开启的。

    需要在setting全局参数中配置开启二级缓存

    conf.xml:

    <settings>
            <setting name="cacheEnabled" value="true"/>默认是false:关闭二级缓存
    <settings>

    在userMapper.xml中配置:

    <!--在当前内部Mapper中打开二级缓存-->
    <cache eviction="LRU" flushInterval="60000" size="512" readOnly="true"/>
    <!--引用全局缓存配置文件-->
    <cache type="org.mybatis.caches.ehcache.LoggingEhcache"/>
    当前 mapper下所有语句开启二级缓存
    这里配置了一个LRU缓存,并每隔60秒刷新,最大存储512个对象,而却返回的对象是只读的。
     
    cache元素用来开启当前mapper的namespace下的二级缓存,该元素的属性设置如下:
    flushInterval:
      刷新间隔,可以被设置为任意的正整数,而且它们代表一个合理的毫秒形式的时间段,默认情况下是不设置的,也就是没有刷新间隔,缓存仅仅调用语句时刷新。
     
    size:
      缓存数目,可以被设置为任意正整数,要记住你的缓存对象数目和你运行环境可用内存资源数目,默认值是1024.
     
    readOnly:
      只读,属性可以被设置为true或false,只读的缓存会给所有调用者返回缓存对象的相同实例,因此这些对象不能被修改。
      这提供了很重要的性能优势,可读写的缓存会返回缓存对象的拷贝(通过序列化),这会慢一些,但是安全,因此默认是false。
     
    eviction:收回策略,默认为LRU,有如下几种:
      LRU:最近最少使用的策略,移除最长时间不被使用的对象。
      FIFO:先进先出策略,按对象进入缓存的顺序来移除它们。
      SOFT:软引用策略,移除基于垃圾回收器状态和软引用规则的对象。
      WEAK:弱引用策略,更积极地移除基于垃圾收集器状态和弱引用规则的对象。
     
    若想禁用当前select语句的二级缓存,添加useCache="false"修改如下:
    <select id="getCountByName" parameterType="java.util.Map" 
    resultType="INTEGER" statementType="CALLABLE" useCache="false">
    具体流程:
      1).当一个sqlseesion执行了一次select后,在关闭此session的时候,会将查询结果缓存到二级缓存
      2).当另一个sqlsession执行select时,首先会在他自己的一级缓存中找,如果没找到,就回去二级缓存中找,找到了就返回,就不用去数据库了,从而减少了数据库压力提高了性能。
     
    注意事项一:
      1).如果SqlSession执行了DML操作(insert、update、delete),并commit了,那么mybatis就会清空当前mapper缓存中的所有缓存数据,这样可以保证缓存中的存的数据永远和数据库中一致,避免出现脏读
     
      2).mybatis的缓存是基于[namespace:sql语句:参数]来进行缓存的,意思就是SqlSession的HashMap存储缓存数据时,是使用[namespace:sql:参数]作为key,查询返回的语句作为value保存的。
     
    注意事项二:
      1):使用二级缓存时,与查询结果映射的java对象必须实现java.io.Serializable接口的序列化和反序列化操作,如果存在父类,其成员都需要实现序列化接口,
        实现序列化接口是为了对缓存数据进行序列化和反序列化操作,因为二级缓存数据存储介质多种多样,不一定在内存,有可能是硬盘或者远程服务器。
     
    例:-1242243203:1146242777:winclpt.bean.userMapper.getUser:0:2147483647:select * from user where id=?:19

    全局配置文件:

    ehcache.xml:

    <ehcache>
    
        <!--临时文件目录  可以自己设置-->
        <diskStore path="java.io.tmpdir"/>
    
        <!--
        maxElementsInMemory:在内存中最大的存储量
        eternal:是否在内存中永远不销毁
        timeToIdleSeconds:在缓存中闲置多少时间之后销毁,默认单位是S
        timeToLiveSeconds:在缓存中存活多少时间之后销毁,无论是否有人使用,默认单位是S
        overflowToDisk:当缓存满的时候是否保存到磁盘中
        diskPersistent:磁盘中的文件是否永久保存
        diskExpiryThreadIntervalSeconds:检测线程运行时间间隔!默认单位是S
    
    
        *******************************************************
        memoryStoreEvictionPolicy  :  缓存清理策略
        1.LRU (least recently  used) 最近最少使用
           每个缓存的元素都有一个时间戳,当缓存容量满的时候,需要腾出来新位置给新缓存元素,
           这时候,会比较时间戳然后删除符合条件的缓存元素
    
        2.LFU (least frequently used )最少使用
             一直以来最少使用的缓存元素,缓存元素中有一个hit值,hit值最少的将会清除!
    
        3.FIFO(first in  first out)  先进先出
        -->
        <defaultCache
                maxElementsInMemory="10000"
                eternal="false"
                timeToIdleSeconds="120"
                timeToLiveSeconds="120"
                overflowToDisk="true"
                diskPersistent="false"
                diskExpiryThreadIntervalSeconds="120"
                memoryStoreEvictionPolicy="LRU"
        />
    </ehcache>

    参考:

    demo:

    END:

      对于MyBatis 缓存的内容仅做了解即可,因为面对一定规模的数据量,内置的Cache 方式就派不上用场了;并且对查询结果集做缓存并不是MyBatis 框架擅长的,它专心做的应该是SQL 映射。
      所以采用 OSCache 、Memcached 等专门的缓存服务器来做更为合理。
     
  • 相关阅读:
    thinkphp5 tp5 命名空间 报错 Namespace declaration statement has to be the very first statement in the script
    开启 php 错误 提示 php-fpm 重启 nginx 500错误 解决办法 wdlinux lnmp 一键包 php脚本无法解析执行
    js 设置 cookie 定时 弹出层 提示层 下次访问 不再显示 弹窗 getCookie setCookie setTimeout
    php 二维数组 转字符串 implode 方便 mysql in 查询
    nginx 重启 ps -ef|grep nginx kill -HUP 主进程号
    jquery bootstrap help-block input 表单 提示 帮助 信息
    jquery 倒计时 60秒 短信 验证码 js ajax 获取
    jQuery如何获取同一个类标签的所有的值 遍历
    linux下C语言文件操作相关函数
    gcc,gdb用法
  • 原文地址:https://www.cnblogs.com/mlq2017/p/9809599.html
Copyright © 2011-2022 走看看