十、MyBatis的缓存

@toc

十、MyBatis的缓存

10.1 MyBatis的一级缓存

一级缓存是SqlSession级别的,通过同一个SqlSession查询的数据会被缓存,下次查询相同的数据,就会从缓存中直接获取,不会从数据库重新访问使一级缓存。

一级缓存失效的四种情况

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

场景1:判断同一个sqlSession是否查询1级缓存,答案:会查询1级缓存

ini 复制代码
@Test
public void testCache1(){
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        CacheMapper cacheMapper1 = sqlSession.getMapper(CacheMapper.class);
        System.out.println(cacheMapper1.getAddressByUserId(1));
        CacheMapper cacheMapper2 = sqlSession.getMapper(CacheMapper.class);
        System.out.println(cacheMapper2.getAddressByUserId(1));
    }

结果日志打印:

场景2:判断不同sqlSession是否查询1级缓存,答案:不会查询1级缓存

ini 复制代码
@Test
public void testCache2(){
        SqlSession sqlSession1 = SqlSessionUtils.getSqlSession();
        CacheMapper cacheMapper1 = sqlSession1.getMapper(CacheMapper.class);
        System.out.println(cacheMapper1.getAddressByUserId(1));
        SqlSession sqlSession2 = SqlSessionUtils.getSqlSession();
        CacheMapper cacheMapper2 = sqlSession2.getMapper(CacheMapper.class);
        System.out.println(cacheMapper2.getAddressByUserId(1));
    }

结果日志打印:

场景3:判断相同sqlSession中间执行一次清除后,是否查询1级缓存,答案:不会查询1级缓存

ini 复制代码
@Test
public void testCache3(){
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        CacheMapper cacheMapper = sqlSession.getMapper(CacheMapper.class);
        System.out.println(cacheMapper.getAddressByUserId(1));
        sqlSession.clearCache();
        System.out.println(cacheMapper.getAddressByUserId(1));
    }

结果日志打印:

10.2 MyBatis的二级缓存

二级缓存是SqlSessionFactory级别,通过同一个SqlSessionFactory创建的SqlSession查询的结果会被缓存;此后若再次执行相同的查询语句,结果就会从缓存中获取

二级缓存开启的条件

  1. 在核心配置文件中,设置全局配置属性cacheEnabled="true",默认为true,不需要设置
  2. 在映射文件中设置标签<cache />
xml 复制代码
<mapper namespace="com.mybatis.mapper.CacheMapper">
    <cache/>    
</mapper>
  1. 二级缓存必须在SqlSession关闭或提交之后有效 4. 查询的数据所转换的实体类类型必须实现序列化的接口
less 复制代码
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Address implements Serializable {
    //id
    private Integer id;
    //用户名称
    private String name;
    //用户ID
    private Integer userId;

    private List<User> userList = new ArrayList<>();
}

使二级缓存失效的情况:两次查询之间执行了任意的增删改,会使一级和二级缓存同时失效。

场景1:验证二级缓存生效的问题,结论:没有SqlSession关闭或提交之后缓存开启不生效

ini 复制代码
@Test
public void testCache4(){
        try {
            InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
            SqlSession sqlSession1 = sqlSessionFactory.openSession(true);
            CacheMapper mapper1 = sqlSession1.getMapper(CacheMapper.class);
            System.out.println(mapper1.getAddressByUserId(1));
            SqlSession sqlSession2 = sqlSessionFactory.openSession(true);
            CacheMapper mapper2 = sqlSession2.getMapper(CacheMapper.class);
            System.out.println(mapper2.getAddressByUserId(1));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

结果日志打印:

执行sqlSession1.close();之后验证效果,如图

ini 复制代码
@Test
public void testCache4(){
        try {
            InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
            SqlSession sqlSession1 = sqlSessionFactory.openSession(true);
            CacheMapper mapper1 = sqlSession1.getMapper(CacheMapper.class);
            System.out.println(mapper1.getAddressByUserId(1));
            sqlSession1.close();
            SqlSession sqlSession2 = sqlSessionFactory.openSession(true);
            CacheMapper mapper2 = sqlSession2.getMapper(CacheMapper.class);
            System.out.println(mapper2.getAddressByUserId(1));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

结果日志打印:

10.3 二级缓存的相关配置

MyBatis缓存查询的顺序

  • 先查询二级缓存,因为二级缓存中可能会有其他程序已经查出来的数据,可以拿来直接使用。
  • 如果二级缓存没有命中,再查询一级缓存
  • 如果一级缓存也没有命中,则查询数据库
  • SqlSession关闭之后,一级缓存中的数据会写入二级缓存

10.4 整合第三方缓存EHCache

问题:为啥需要使用第三方缓存插件,而不是完全直接使用Mybatis自带的缓存?

答案:Mybatis自带的缓存是持久层框架,会把缓存写入磁盘中,而读写磁盘肯定会涉及大量的IO操作,明显会导致效率低,如果能从内存中读取缓存内容那就会快很多,所以需要使用第三方缓存插件。

注意:第三方缓存插件代替的只是"二级缓存"而已,无法代替一级缓存。

  • 1.添加依赖
xml 复制代码
<!-- Mybatis EHCache整合包 -->
<dependency>
	<groupId>org.mybatis.caches</groupId>
	<artifactId>mybatis-ehcache</artifactId>
	<version>1.2.1</version>
</dependency>
<!-- slf4j日志门面的一个具体实现 -->
<dependency>
	<groupId>ch.qos.logback</groupId>
	<artifactId>logback-classic</artifactId>
	<version>1.2.3</version>
</dependency>
  • 2.各jar包功能
  • 3.创建EHCache的配置文件ehcache.xml
xml 复制代码
<?xml version="1.0" encoding="utf-8" ?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
    <!-- 磁盘保存路径 -->
    <diskStore path="D:\atguigu\ehcache"/>
    <defaultCache
            maxElementsInMemory="1000"
            maxElementsOnDisk="10000000"
            eternal="false"
            overflowToDisk="true"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU">
    </defaultCache>
</ehcache>
  • 4.设置二级缓存的类型
ini 复制代码
<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
  • 5.EHCache配置文件说明

本人其他相关文章链接

1.一、MyBatis简介:MyBatis历史、MyBatis特性、和其它持久化层技术对比、Mybatis下载依赖包流程 2.二、搭建MyBatis采用xml方式,验证CRUD(增删改查操作) 3.三、MyBatis核心配置文件详解 4.四、MyBatis获取参数值的两种方式(重点) 5.五、MyBatis的增删改查模板(参数形式包括:String、对象、集合、数组、Map) 6.六、MyBatis特殊的SQL:模糊查询、动态设置表名、校验名称唯一性 7.七、MyBatis自定义映射resultMap 8.八、(了解即可)MyBatis懒加载(或者叫延迟加载) 9.九、MyBatis动态SQL 10.十、MyBatis的缓存 11.十一、MyBatis的逆向工程 12.十二、MyBatis分页插件

重要信息

相关推荐
程序员老舅3 小时前
啃透 I2C 驱动开发,才算入门嵌入式 Linux 内核驱动
数据结构·驱动开发·b树·内核·嵌入式·嵌入式开发·i2c
奔跑中的小象3 小时前
统信UOS + 天数AI卡部署SGLang服务手册
人工智能·uos·sglang·天数智芯
DevSecOps选型指南4 小时前
中国版Mythos,为何是悬镜安全灵脉CodeAI?
人工智能·安全
Shockang4 小时前
LangGraph 状态机实战
人工智能
刹那芳华19924 小时前
循环神经网络的从零开始实现(RNN)
人工智能·rnn·深度学习
阿童木写作4 小时前
跨境图片翻译工具多合一,批量图片视频字幕翻译加智能抠图
人工智能·python·音视频·语音识别
科技之门4 小时前
AI3D从建模到贴图、绑骨和动画的完整流程怎么做?V2Fun完整工作流指南
人工智能·3d·贴图
宇宙第一小趴菜4 小时前
二、机器学习的应用领域和发展史
人工智能·机器学习
前端开发江鸟4 小时前
我写过 MCP Server,却一直以为 MCP 只有 Tool
人工智能
天国梦5 小时前
自习室智能化升级避坑指南:天学网AI智习室方案实测与选型建议
大数据·人工智能