zoukankan      html  css  js  c++  java
  • mybatis 缓存

    6. MyBatis缓存

    1. 一级缓存: 基于PerpetualCache 的 HashMap本地缓存,其生命周期为 Session,当 Session flush 或 close 之后,该Session中的所有 Cache 就将清空。

    2. 二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap存储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。

    3. 对于缓存数据更新机制,当某一个作用域(一级缓存Session/二级缓存Namespaces)进行了 C/U/D 操作后,默认该作用域下所有 select 中的缓存将被clear。

    面试必考

    1.缓存应用场景

    查询频率比较高,而且数据信息不经常变动。客户档案定义 ,托运部定义。

    2.缓失效的问题

    缓存是有过期事件的 。

    滑动过期:从最后一次使用开始往后推算一段时间

    绝对过期:一段时间内一定会失效

    3.缓存是一把双刃剑

    哲学:缓存,快,高速,

    容易炸,使用不当,起不到加速查询的作用。

    Redis ----------->D

    4.缓存的存储结构

    session 的底层map集合 key value

    5.第三方缓存插件

    EhCache

    查询缓存的使用,主要是为了提高查询访问速度。将用户对同一数据的重复查询过程简化,不再每次均从数据库查询获取结果数据,从而提高访问速度。

    6.1 缓存原理
    6.2 缓存分类

    MyBatis查询缓存机制。根据缓存区的作用域与生命周期,可划分为两种:一级缓存和二级缓存。

      MyBatis查询缓存的作用域是根据映射文件的namespace划分的,相同的namespace的mapper查询数据放在同一个缓存区域。不同namespace下的数据互不干扰。无论是一级缓存还是二级缓存,都是按照namespace进行分别存放的。

      但是一级、二级缓存的不同之处在于,SqlSession一旦关闭,则SqlSession中的数据将不存在,即一级缓存就不复存在。而二级缓存的生命周期与整个应用同步,与SqlSession是否关闭无关。换句话说,一级缓存是在同一线程(同一SqlSession)间共享数据,而二级缓存是在不同线程(不同的SqlSession)间共享数据。

    6.3 一级缓存
    6.3.1 一级缓存--从缓存中查找数据的依据:

    缓存的底层实现是一个Map,Map的value是查询结果

    Map的key,即查询依据,使用的ORM架构不同,查询依据是不同的

    MyBatis的查询依据是:Sql的id+SQL语句

    Hibernate的查询依据是:查询结果对象的id

    测试:

    @Test

    public void show(){

    List<Result> list=null;

    SqlSession session= UtilMybatis.getsession();

    try {

    list= session.getMapper(ResultDao.class).findAllResult();

    } catch (Exception e) {

    e.printStackTrace();

    }

    for(Result result:list){

    System.out.println(result);

    }

    System.out.println("==========一级缓存===========");

    try {

    list= session.getMapper(ResultDao.class).findAllResult();

    } catch (Exception e) {

    e.printStackTrace();

    }finally {

    UtilMybatis.closesession(session);

    }

    for(Result result:list){

    System.out.println(result);

    }

    }

    结果:sql只执行一次后将id与sql 存储在一级缓存内(使用同一个session)

    6.3.2 增、删、改对一级缓存的影响

    增删改会清空一级缓存:注意:必须使用insert标签,不能使用select,否则实验做不成功

    测试:

    public void show() throws Exception {

    List<Result> list=null;

    SqlSession session= UtilMybatis.getsession();

    try {

    list= session.getMapper(ResultDao.class).findAllResult();

    } catch (Exception e) {

    e.printStackTrace();

    }

    for(Result result:list){

    System.out.println(result);

    }

    System.out.println("==========增加===========");

    Result result1=new Result();

    result1.setAge(18);

    result1.setScore(80);

    result1.setSubjectName("shuxue");

    Integer count=session.getMapper(ResultDao.class).adderesult(result1);

    System.out.println(count);

    System.out.println("==========一级缓存===========");

    try {

    list= session.getMapper(ResultDao.class).findAllResult();

    } catch (Exception e) {

    e.printStackTrace();

    }finally {

    UtilMybatis.closesession(session);

    }

    for(Result result:list){

    System.out.println(result);

    }

    }

    结果:session用同一个,在添加后在查询因(增加清空一级缓存)故在进行db查询

    6.3.2 内置二级缓存(在同一mapper.xml文件中)

           由于MyBatis从缓存中读取数据的依据与SQL的id相关,而非查询出的对象。所以,使用二级缓存的目的,不是在多个查询间共享查询结果(所有查询中只要查询结果中存在该对象,就直接从缓存中读取,这是对查询结果的共享,Hibernate中的缓存就是为了在多个查询间共享查询结果,但MyBatis不是),而是为了防止同一查询(相同的Sql id,相同的sql语句)的反复执行。

    https://my.oschina.net/KingPan/blog/280167

    http://www.mamicode.com/info-detail-890951.html

    http://blog.csdn.net/isea533/article/details/44566257

    http://blog.csdn.net/u010676959/article/details/43953087

    http://blog.csdn.net/xiadi934/article/details/50786293

    如何开启二级缓存,二级缓存在Mybatis默认是开启(全局配置的某个属性值为true)的,但是开始和能直接使用时两码事。

    1.你cacheEnabled=true,默认值为true

    <setting name="cacheEnabled" value="true"></setting>

    2.你得在Mapper文件中,<cache/>

    <cache

    eviction="FIFO"

    flushInterval="60000"

    size="512"

    readOnly="true"/>

    这个更高级的配置创建了一个 FIFO 缓存,并每隔 60 秒刷新,存数结果对象或列表的 512 个引用,

    而且返回的对象被认为是只读的

    3.Entity Implements Serializable(实体类序列化)

    缓存中对象可用的收回策略

    LRU – 最近最少使用的:移除最长时间不被使用的对象。

    FIFO – 先进先出:按对象进入缓存的顺序来移除它们。

    SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。

    WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。

    默认的是 LRU。

    flushInterval(刷新间隔)可以被设置为任意的正整数,而且它们代表一个合理的毫秒 

    形式的时间段。默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新。

    size(引用数目)可以被设置为任意正整数,要记住你缓存的对象数目和你运行环境的 

    可用内存资源数目。默认值是 1024。

    readOnly(只读)属性可以被设置为 true 或 false。只读的缓存会给所有调用者返回

    缓 存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。

    可读写的缓存 会返回缓存对象的拷贝(通过序列化) 。这会慢一些,但是安全,因此默认是 false。

    6.3.4. 增删改对二级缓存的影响

     1.增删改也会清空二级缓存

          2.对于二级缓存的清空实质上是对value清空为null,key依然存在,并非将Entry<k,v>删除

          3.从DB中进行select查询的条件是:

                  1.缓存中根本不存在这个key

                  2.存在key对应的Entry,但是value为null

    二级缓存的关闭

    全局关闭:

    局部关闭

    二级缓存的使用原则

    1.多个namespace不要操作同一张表

    2.查询大于修改的情况下使用

    6.3.5 引入第三方插件Mybatis集成EhCache

    在MyBatis中通过ehcache配置二级缓存

    1.jar包

    <dependency>

    <groupId>net.sf.ehcache</groupId>

    <artifactId>ehcache</artifactId>

    <version>2.10.4</version>

    </dependency>

    <dependency>

    <groupId>org.mybatis.caches</groupId>

    <artifactId>mybatis-ehcache</artifactId>

    <version>1.1.0</version>

    </dependency>

       2.在小配置中添加一个缓存类

    在小配置中输入EhcacheCache 并选中 双击shift

    点击EhcacheCache 出现

    鼠标右击出现

    粘贴在

    粘贴前:

    粘贴后:

       3.在src下植入ehcache.xml文件

    <ehcache>

    <diskStore path="java.io.tmpdir"/>

    <defaultCache

    maxElementsInMemory="10000"

    eternal="false"

    timeToIdleSeconds="120"

    timeToLiveSeconds="120"

    overflowToDisk="true"

    />

    <cache name="sampleCache1"

    maxElementsInMemory="10000"

    eternal="false"

    timeToIdleSeconds="300"

    timeToLiveSeconds="600"

    overflowToDisk="true"

    />

    <cache name="sampleCache2"

    maxElementsInMemory="1000"

    eternal="true"

    timeToIdleSeconds="0"

    timeToLiveSeconds="0"

    overflowToDisk="false"

    /> -->

    </ehcache>

    测试: public void show() throws Exception {

    List<Result> list=null;

    SqlSession session= UtilMybatis.getsession();

    try {

    list= session.getMapper(ResultDao.class).findAllResult();

    } catch (Exception e) {

    e.printStackTrace();

    }finally {

    UtilMybatis.closesession(session); //session关闭

    }

    for(Result result:list){

    System.out.println(result);

    }

    System.out.println("========二级缓存=============");

    SqlSession session1= UtilMybatis.getsession();

    try {

    list= session1.getMapper(ResultDao.class).findAllResult();

    } catch (Exception e) {

    e.printStackTrace();

    }finally {

    UtilMybatis.closesession(session1);

    }

    for(Result result:list){

    System.out.println(result);

    }

    }

    结果:sql语句执行一次

  • 相关阅读:
    编译原理-第二章 一个简单的语法指导编译器-2.4 语法制导翻译
    编译原理-第二章 一个简单的语法指导编译器-2.3 语法定义
    编译原理-第二章 一个简单的语法指导编译器-2.2 词法分析
    LeetCode 1347. Minimum Number of Steps to Make Two Strings Anagram
    LeetCode 1348. Tweet Counts Per Frequency
    1349. Maximum Students Taking Exam(DP,状态压缩)
    LeetCode 1345. Jump Game IV(BFS)
    LeetCode 212. Word Search II
    LeetCode 188. Best Time to Buy and Sell Stock IV (动态规划)
    LeetCode 187. Repeated DNA Sequences(位运算,hash)
  • 原文地址:https://www.cnblogs.com/Java60-123456/p/10678654.html
Copyright © 2011-2022 走看看