• MyBatis缓存



    学习视频来自于:秦疆(遇见狂神说)Bilibili地址
    他的自学网站:kuangstudy

    你只有走完必须走的路,才能过想过的生活


    一、MyBatis缓存(了解即可)

    1.1 简介

    1.1.1 什么是缓存[Cache]

    • 存在内存中的临时数据。
    • 将用户经常查询的数据放在缓存(内存)中,用户去查询数据就不用从磁盘上(关系型数据库查询文件)查询,从缓存中查询,从而提高查询效率,解决了高并发系统的性能问题。

    1.1.2 为什么使用缓存

    • 减少和数据库的交互次数,减少系统开销,提高系统效率。

    1.1.3 什么样的数据能使用缓存

    • 经常查询并且不经常改变的数据。

    1.1.4 MyBatis缓存

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

    1.2 一级缓存

    1.2.1 介绍

    • 一级缓存也叫本地缓存:
      • 与数据库同一次会话期间查询到的数据会放在本地缓存中。
      • 以后如果需要获取相同的数据,直接从缓存中拿,没必要再去查询数据库。
    • 条件
      • 同一个SqlSession
      • SqlSession关闭,一级缓存就消失了

    1.2.2 测试

    1. 开启日志(可以有效地查看SQL语句和缓存电泳)
    2. 测试在一个SqlSession中查询两次记录
    3. 查看日志输出

    测试代码

    @Test
    public void queryById(){
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        String id = "0a547141ea664a438268c8f20e5dd049";
        Blog blog = mapper.queryById(id);
        System.out.println(blog);
        System.out.println("===================================");
        Blog blog1 = mapper.queryById(id);
        System.out.println(blog1);
        System.out.println(blog.equals(blog1));
        sqlSession.close();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    日志
    在这里插入图片描述

    1.2.3 缓存失效的情况

    1. 查询不同
      在这里插入图片描述

    2. 增删改操作后,可能会改变原来的数据,必定会刷新缓存
      在这里插入图片描述

    3. 查询不同的Mapper.xml

    4. 手动清理缓存

    sqlSession.clearCache(); // 手动清理缓存
    
    • 1

    小结

    • 一级缓存默认是开启的,只在一次SqlSession中有效,也就是拿到连接到关闭连接这个区间段!
    • 一级缓存相当于一个Map。

    1.3 二级缓存

    1.3.1 介绍

    • 二级缓存也叫全局缓存,一级缓存作用域太低了,所以诞生了二级缓存。
    • 基于namespace级别的缓存,一个名称空间,对应一个二级缓存。
    • 工作机制
      • 一个会话查询一条数据,这个数据就会被放在当前会话的一级缓存中。
      • 如果当前会话关闭了,这个会话对应的一级缓存就没了;但是我们想要的是,会话关闭了,一级缓存中的数据被保存到二级缓存中。
      • 新的会话查询信息,就可以从二级缓存中获取内容。
      • 不同的mapper查出的数据就会放在自己对应的缓存(map)中。

    1.3.2 测试

    1. 在mybatis-config.xml开启全局缓存
    设置名描述有效值默认值
    cacheEnabled全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。true、falsetrue
    
    <setting name="cacheEnabled" value="true"/>
    
    • 1
    • 2
    1. 在要使用二级缓存的Mapper中开启
    
    <cache/>
    
    • 1
    • 2
    1. 也可以自定义参数
    
    <cache
            eviction="FIFO"
            flushInterval="60000"
            size="512"
            readOnly="true"/>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    测试代码

    @Test
    public void queryById(){
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        String id = "0a547141ea664a438268c8f20e5dd049";
        Blog blog = mapper.queryById(id);
        System.out.println(blog);
        sqlSession.close();
        System.out.println("================关闭之后查询===================");
        SqlSession sqlSession1 = MybatisUtil.getSqlSession();
        BlogMapper mapper1 = sqlSession1.getMapper(BlogMapper.class);
        Blog blog1 = mapper1.queryById(id);
        System.out.println(blog1);
        sqlSession1.close();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在这里插入图片描述

    可以在单个查询语句上指定不使用二级缓存

    <select id="queryById" resultType="blog" useCache="false">
        select * from blog
        <where>
            id = #{id}
        where>
    select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    问题
    如果没有自定义参数,则会报错,我们需要将实体类序列化!

    // Cause: java.io.NotSerializableException: com.kuang.pojo.User
    
    • 1

    小结

    1. 只要开启了二级缓存,在同一个Mapper下就有效。
    2. 所有的数据都会先放在一级缓存中。
    3. 只有当会话提交或者关闭的时候,才会提交到二级缓存中。

    1.4 缓存原理

    在这里插入图片描述

    1.5 自定义缓存Ehcache

    1.5.1 介绍

    EhCache 是一个纯Java的进程内缓存框架,具有快速、精干等特点,是Hibernate中默认的CacheProvider。
    Ehcache是一种广泛使用的开源Java分布式缓存。主要面向通用缓存。

    1.5.2 使用

    maven地址

    
    <dependency>
        <groupId>org.mybatis.cachesgroupId>
        <artifactId>mybatis-ehcacheartifactId>
        <version>1.2.2version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    BlogMapper.xml

    <cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
    
    • 1

    ehcache.xml

    
    <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
             updateCheck="false">
        
        <diskStore path="./tmpdir/Tmp_EhCache"/>
    
        <defaultCache
                eternal="false"
                maxElementsInMemory="10000"
                overflowToDisk="false"
                diskPersistent="true"
                timeToIdleSeconds="1800"
                timeToLiveSeconds="259200"
                memoryStoreEvictionPolicy="LRU">
        defaultCache>
    
    
    ehcache>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    测试代码

    @Test
    public void queryById(){
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        String id = "0a547141ea664a438268c8f20e5dd049";
        Blog blog = mapper.queryById(id);
        System.out.println(blog);
        sqlSession.close();
        System.out.println("================关闭之后查询===================");
        SqlSession sqlSession1 = MybatisUtil.getSqlSession();
        BlogMapper mapper1 = sqlSession1.getMapper(BlogMapper.class);
        Blog blog1 = mapper1.queryById(id);
        System.out.println(blog1);
        sqlSession1.close();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    日志没有区别
    在这里插入图片描述

  • 相关阅读:
    Android Kotlin 协程初探 | 京东物流技术团队
    springboot集成Actuator+Prometheus+Grafana
    【阿里云】图像识别
    Vue安装并使用Vue-CLI构建SPA项目并实现路由
    Python Pandas数据处理作图——波尔共振实验
    4位资深专家多年大厂经验分享出Flink技术架构设计与实现原理
    【译】Visual Studio 2013 退役 :旧版本 Visual Studio 的支持提醒
    【Java 进阶篇】深入理解 Bootstrap 导航条与分页条
    R语言快速实现图片布局(1)
    少儿编程之冒泡排序
  • 原文地址:https://blog.csdn.net/zhao854116434/article/details/126047913