• MyBatis的一级缓存和二级缓存


    碰见了不懂,学学接着

    还是提问:首先,什么是缓存?

    缓存是什么?

    缓存其实就是存储在内存中的临时数据,这里的数据量会比较小,一般来说,服务器的内存也是有限的,不可能将所有的数据都放到服务器的内存里面,所以, 只会把关键数据放到缓存中,缓存因为速度快,使用方便而广泛使用

    缓存在数据库中对查询结果的保存,可以使用缓存,这样能减少跟数据库交互的次数,进而提高响应速度。

    Mybatis提供的缓存

    Mybatis也提供了对缓存的支持,分为一级缓存和二级缓存,可以通过下图和下表来理解:

    一级缓存?

    一级缓存是默认开启的,它在一个sqlSession会话里面的所有查询操作都会保存到缓存中,一般来说一个请求中的所有增删改查操作都是在同一个sqlSession里面的,所以我们可以认为每个请求都有自己的一级缓存,如果同一个sqlSession会话中2 个查询中间有一个 insert 、update或delete 语句,那么之前查询的所有缓存都会清空。

    例如下面Mybatis的代码:

    代码中所走的所有查询操作都会进行默认进行一级缓存,一旦关闭sqlSession会话,缓存则会刷新

    在这里插入图片描述

    //1.加载核心配置文件
    InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
    
    //2.获取SqlSession工厂对象
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
    
    //3.通过工厂对象获取SqlSession对象
    SqlSession sqlSession = sqlSessionFactory.openSession(true);
    
    //4.获取StudentMapper接口的实现类对象
    StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
    
    //5.调用实现类对象中的方法,接收结果
    Student stu = new Student(4,"赵六",36);
    Integer result = mapper.update(stu);
    
    // 这中间所走的所有查询操作都会进行缓存,一旦关闭sqlSession会话,缓存则会刷新
    
    //6.处理结果
    System.out.println(result);
    
    //7.释放资源
    // 清除缓存
    sqlSession.clearCache();
    // 释放会话
    sqlSession.close();
    // 关闭流
    is.close();
    
    • 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

    这样看也是不明显的,我们在mybatis 的配置文件中加入以下配置,开启sql日志,每一个sql代表请求了一次数据库,这样我们就可以根据sql来判断是否使用了缓存。

    <settings>
        
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    settings>
    
    • 1
    • 2
    • 3
    • 4

    或者配置log4j输出日志

    
    <settings>
        <setting name="logImpl" value="log4j"/>
    settings>
    
    • 1
    • 2
    • 3
    • 4

    我们查询两次:

    //5.调用实现类对象中的方法,接收结果
    Student stu = new Student(4,"赵六",36);
    Integer result = mapper.update(stu);
    System.out.println(stu);
    Student stu2 = new Student(4,"赵六",36);
    System.out.println(stu2);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    我们可以看到控制台其实就执行了一次sql代码:
    在这里插入图片描述
    说明他默认一级缓存了

    一级缓存什么时候过期?什么时候清空?

    一级缓存无过期时间,只有生命周期
    MyBatis在开启一个数据库会话时,会创建一个新的SqlSession对象,SqlSession对象中会有一个Executor对象,Executor对象中持有一个PerpetualCache对象,当会话结束时,SqlSession对象及其内部的Executor对象还有PerpetualCache对象也一并释放掉。

    二级缓存?

    二级缓存是全局的,也就是说;多个请求可以共用一个缓存,二级缓存需要手动开启,有2种方式配置二级缓存,缓存会先放在一级缓存中,当sqlSession会话提交或者关闭时才会将一级缓存刷新到二级缓存中;

    开启二级缓存后,用户查询时,会先去二级缓存中找,找不到在去一级缓存中找;

    如下图二级缓存的工作原理图
    在这里插入图片描述

    什么时候存?

    在关闭sqlsession后(close),才会把该sqlsession一级缓存中的数据添加到namespace的二级缓存中。

    注意:开启了二级缓存后,建议将要缓存的pojo实现Serializable接口,为了将缓存数据取出执行反序列化操作,因为二级缓存数据存储介质多种多样,不一定只存在内存中,有可能存在硬盘中。
    在这里插入图片描述

    怎么配置?

    第一种配置:

    单个mapper配置,主需要在需要开启二级缓存的mapper.xml文件中加入以下配置即可开启。

    
      <cache />
    
    • 1
    • 2

    注意一定要加到xxMapper.xml的文件内,千万不要加到mybatis 的主配置文件里面了,会报错的,正确的配置位置如下图所示:

    在这里插入图片描述

    第二种配置:

    所有的mapper都开启二级缓存,在mybatis.xml中加入以下配置即可

    
    <settings>
        <setting name="logImpl" value="log4j"/>
        
        <setting name="cacheEnabled" value="true"/>
    settings>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述

    二级缓存什么时候过期?什么时候清空?

    二级缓存的过期时间是这个cache的过期时间,是flushInterval,意味着整个清空缓存cache,所以不需要后台线程去定时检测。

    每当存取数据的时候,都有检测一下cache的生命时间,默认是1小时,如果这个cache存活了一个小时,那么将整个清空一下。

    缓存注意事项:

    另外,缓存还有以下几种情况需要注意

    1. 映射语句文件中的所有 select 语句的结果将会被缓存。

    2. 映射语句文件中的所有 insert、update 和 delete 语句会刷新缓存。

    3. 缓存会使用最近最少使用算法(LRU, Least Recently Used)算法来清除不需要的缓存。

    4. 缓存不会定时进行刷新(也就是说,没有刷新间隔)。

    5. 缓存会保存列表或对象(无论查询方法返回哪种)的 1024 个引用。

    6. 缓存会被视为读/写缓存,这意味着获取到的对象并不是共享的,可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。

  • 相关阅读:
    使用IntelliJ Idea开发Spark应用程序
    工程制图复习题
    Python 标准库之 fileinput 和 文件迭代器
    指针及其应用
    Object中的方法
    组合模式(Composite Pattern)
    LeetCode-653. Two Sum IV - Input is a BST [C++][Java]
    Linux环境redis外网连接配置
    关于Qt5中QListWidgetItem不显示的问题
    [架构之路-247]:目标系统 - 设计方法 - 软件工程 - 结构化方法的基本思想、本质、特点以及在软件开发、在生活中的应用
  • 原文地址:https://blog.csdn.net/weixin_45525272/article/details/126084094