【MyBatis】一级缓存 二级缓存详解

【MyBatis系列】基础篇——curd语法

【MyBatis系列】基础篇——参数传递

【MyBatis系列】基础篇——ResultMap自定义映射

【MyBatis系列】基础篇——动态sql

【MyBatis系列】基础篇——一级缓存 二级缓存

【MyBatis系列】基础篇——驼峰式命名配置

【MyBatis系列】插件篇——逆向工程(代码生成器)

【MyBatis系列】插件篇——PageHelper分页


文章目录

  • 【前言】
  • 【正文】
    • 一、一级缓存
      • (一)简介
      • (二)使用
      • (三)失效情况
    • 二、二级缓存
      • (一)简介
      • (二)配置
        • 第一步:导入jar包
        • 第二步:在mybatis全局配置文件开启二级缓存
        • 第三步:创建第三方缓存插件配置文件(ehcache)
        • 第四步 在映射配置文件中添加ehcache缓存支持配置
        • 第五步 查询对应实体类实现Serializable接口
        • 第六步 在查询select标签添加使用缓存属性
        • 补充:
      • (三)使用
    • 缓存的相关属性设置
  • 【结语】


【前言】

  1. MyBatis 包含一个非常强大的查询缓存特性,它可以非常方便地配置和定制。缓存可以极大的提升查询效率。
  2. MyBatis系统中默认定义了两级缓存。
  3. 默认情况下,只有一级缓存(SqlSession级别的缓存,也称为本地缓存)开启。
  4. 二级缓存需要手动开启和配置,它是基于namespace级别的缓存。
  5. 为了提高扩展性。MyBatis定义了缓存接口Cache。我们可以通过实现Cache接口来自定义二级缓存。

【正文】

一、一级缓存

(一)简介

  • mybatis的一级缓存是默认打开的;
  • 一级缓存使用范围:sqlsession;
  • 一级缓存数据是使用map集合封装的:
  • 同一次会话期间只要查询过的数据都会保存在当前SqlSession的一个Map中:
    key: hashCode+查询的SqlId+编写的sql查询语句+参数
    value:查询结果

(二)使用

接口:

    /**
     * 根据部门id查询部门信息
     * @param did
     * @return
     */
    public Dept getDeptById(int did);

mapper:

    
    <select id="getDeptById" resultType="com.mybatislearn.entity.Dept">
    select * from tbl_dept where did=#{did}
    select>

实现类:

public class TestMyBatis {
    @Test
    public void test()  throws Exception{
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession session = sqlSessionFactory.openSession(true);
        try {

//     Mapper接口:获取Mapper接口的 代理实现类对象
            EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);

            Dept dept = mapper.getDeptById(1);
            System.out.println(dept);

            Dept dept1 = mapper.getDeptById(2);
            System.out.println(dept1);

        } finally {
            session.close();
        }
    }

}

  • 第一次查:
            Dept dept = mapper.getDeptById(1);
            System.out.println(dept);
  • 第一次查的结果:
    【MyBatis】一级缓存 二级缓存详解_第1张图片

  • 第二次查:

            Dept dept = mapper.getDeptById(1);
            System.out.println(dept);

            Dept dept1 = mapper.getDeptById(1);
            System.out.println(dept1);
  • 第二次查的结果:
    【MyBatis】一级缓存 二级缓存详解_第2张图片
    很显然,第二次查的时候,没有再查询数据库,而是直接从一级缓存里查到了结果,并进行了输出。

  • 查不同的数据

            Dept dept = mapper.getDeptById(1);
            System.out.println(dept);

            Dept dept1 = mapper.getDeptById(2);
            System.out.println(dept1);
  • 查不同的数据的结果
    【MyBatis】一级缓存 二级缓存详解_第3张图片这里如果查不同的数据,从缓存中查不到,因此是执行了两次数据查询的。

(三)失效情况

  1. 不同的SqlSession对应不同的一级缓存(SqlSession session = sqlSessionFactory.openSession(true);
  2. 同一个SqlSession但是查询条件不同(增删改查)
  3. 同一个SqlSession两次查询期间执行了任何一次增删改操作
  4. 同一个SqlSession两次查询期间手动清空了缓存(session.clearCache();

二、二级缓存

(一)简介

  • mybatis里面二级缓存默认没有打开的,需要手动打开,并且二级缓存使用需要依赖第三方插件
  • 二级缓存使用范围namespace访问
  • 二级缓存在 SqlSession 关闭或提交之后才会生效

(二)配置

第一步:导入jar包

【MyBatis】一级缓存 二级缓存详解_第4张图片【MyBatis】一级缓存 二级缓存详解_第5张图片

第二步:在mybatis全局配置文件开启二级缓存

【MyBatis】一级缓存 二级缓存详解_第6张图片

第三步:创建第三方缓存插件配置文件(ehcache)

ehcache.xml:


<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
    
    <diskStore path="E:\mybatis-learn\ehcache" />

    <defaultCache
            maxElementsInMemory="1000"
            maxElementsOnDisk="10000000"
            eternal="false"
            overflowToDisk="true"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU">
    defaultCache>
ehcache>

第四步 在映射配置文件中添加ehcache缓存支持配置

mapper.xml:
【MyBatis】一级缓存 二级缓存详解_第7张图片

第五步 查询对应实体类实现Serializable接口

第六步 在查询select标签添加使用缓存属性

useCache="true"

    <select id="getDeptById" resultType="com.mybatislearn.entity.Dept" useCache="true">
    select * from tbl_dept where did=#{did}
    select>

补充:

  1. 二级缓存(second level cache),全局作用域缓存
  2. 二级缓存默认不开启,需要手动配置
  3. MyBatis提供二级缓存的接口以及实现,缓存实现要求POJO实现Serializable接口
  4. 二级缓存在 SqlSession 关闭或提交之后才会生效
  5. 二级缓存使用的步骤:
    ① 全局配置文件中开启二级缓存
    ② 需要使用二级缓存的映射文件处使用cache配置缓存
    ③ 注意:POJO需要实现Serializable接口
  6. 二级缓存相关的属性
    eviction=“FIFO”:缓存回收策略:
    LRU – 最近最少使用的:移除最长时间不被使用的对象。
    FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
    SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
    WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
    默认的是 LRU。
    flushInterval:刷新间隔,单位毫秒
    默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新
    size:引用数目,正整数
    代表缓存最多可以存储多少个对象,太大容易导致内存溢出
    readOnly:只读,true/false
    true:只读缓存;会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。
    false:读写缓存;会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全,因此默认是 false。

(三)使用

实现类:

public class TestMyBatis {
    @Test
    public void test()  throws Exception{
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession session1 = sqlSessionFactory.openSession(true);
        SqlSession session2 = sqlSessionFactory.openSession(true);
        try {

//     Mapper接口:获取Mapper接口的 代理实现类对象
            EmployeeMapper mapper1 = session1.getMapper(EmployeeMapper.class);
            EmployeeMapper mapper2 = session2.getMapper(EmployeeMapper.class);


            Dept dept1 = mapper1.getDeptById(1);
            System.out.println("dept1"+dept1);

            //二级缓存在sqlsession关闭或提交后才会生效
            session1.close();

            Dept dept2 = mapper2.getDeptById(1);
            System.out.println("dept2"+dept2);
        } finally {
            session2.close();
        }
    }

}

结果:
【MyBatis】一级缓存 二级缓存详解_第8张图片

缓存的相关属性设置

  1. 全局setting的cacheEnable:
    配置二级缓存的开关,一级缓存一直是打开的。
  2. select标签的useCache属性:
    配置这个select是否使用二级缓存。一级缓存一直是使用的
  3. sql标签的flushCache属性:
    增删改默认flushCache=true。sql执行以后,会同时清空一级和二级缓存。
    查询默认 flushCache=false。
  4. sqlSession.clearCache():只是用来清除一级缓存。

【结语】

实践出真知,practice make perfect!

你可能感兴趣的:(▶后端,#,【Mybatis】,▶框架,mybatis,缓存,框架,java,后端)