当前位置: 首页 > news >正文

MyBatis 之缓存机制核心解析

目录

1. 缓存

2. 一级缓存

2.1. 清空一级缓存

 3. 二级缓存

 4. 总结


前言

大家好,我是艺杯羹(๑•̀ㅂ•́)و✧
本文来讲解MyBatis中的缓存,旨在帮助读者更好的理解和掌握(๑•̀ㅂ•́)و✧

个人主页:艺杯羹

系列专栏:MyBatis

1. 缓存

缓存是内存当中一块存储数据的区域,目的是提高查询效率
MyBatis会将查询结果存储在缓存当中,当下次执行相同的SQL时不访问数据库,而是直接从缓存中获取结果,从而减少服务器的压力

  • 什么是缓存?
    存在于内存中的一块数据

  • 缓存有什么作用?
    减少程序和数据库的交互,提高查询效率降低服务器和数据库的压力

  • 什么样的数据使用缓存?
    经常查询但不常改变的,改变后对结果影响不大的数据

  • MyBatis 缓存分为哪几类?
    一级缓存和二级缓存

  • 如何判断两次 Sql 是相同的?

    1. 查询的 Sql 语句相同
    2. 传递的参数值相同
    3. 对结果集的要求相同
    4. 预编译的模板 Id 相同

2. 一级缓存

MyBatis一级缓存也叫本地缓存
SqlSession对象中包含一个Executor对象,Executor对象中包含一个PerpetualCache对象,在该对象存放一级缓存数据
MyBatis的一级缓存是默认开启的,不需要任何的配置

测试一级缓存

@Test
public void testCache1() throws IOException {InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();SqlSessionFactory factory = builder.build(is);SqlSession session = factory.openSession();// 使用同一个SqlSession查询UserMapper mapper1 = session.getMapper(UserMapper.class);UserMapper mapper2 = session.getMapper(UserMapper.class);User user1 = mapper1.findById(1);System.out.println(user1.hashCode());System.out.println("-------------------------------------------");User user2 = mapper2.findById(1);System.out.println(user2.hashCode());
}@Test
public void testCache2() throws IOException {InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();SqlSessionFactory factory = builder.build(is);SqlSession session1 = factory.openSession();SqlSession session2 = factory.openSession();// 使用不同的SqlSession查询UserMapper mapper1 = session1.getMapper(UserMapper.class);UserMapper mapper2 = session2.getMapper(UserMapper.class);User user1 = mapper1.findById(1);System.out.println(user1.hashCode());System.out.println("-------------------------------------------");User user2 = mapper2.findById(1);// 看是否是一个对象System.out.println(user2.hashCode());
}

2.1. 清空一级缓存

进行以下操作可以清空MyBatis一级缓存

  1. ​SqlSession​调用close()​: 操作后SqlSession对象不可用,该对象的缓存数据也不可用
  2. ​SqlSession​调用clearCache()​ / commit()​: 操作会清空一级缓存数据
  3. ​SqlSession​调用增删改方法: 操作会清空一级缓存数据,因为增删改后数据库发生改变,缓存数据将不准确

代码示范

@Test
public void testCache3() throws IOException {InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();SqlSessionFactory factory = builder.build(is);SqlSession session = factory.openSession();UserMapper mapper1 = session.getMapper(UserMapper.class);UserMapper mapper2 = session.getMapper(UserMapper.class);User user1 = mapper1.findById(1);System.out.println(user1.hashCode());//     session.close();//     session.clearCache();//     session.commit();mapper1.delete(2);System.out.println("-------------------------------------------");User user2 = mapper2.findById(1);System.out.println(user2.hashCode());
}

 3. 二级缓存

MyBatis二级缓存也叫全局缓存。数据存放在SqlSessionFactory中,只要是同一个工厂对象创建的SqlSession,在进行查询时都能共享数据。一般在项目中只有一个SqlSessionFactory对象,所以二级缓存的数据是全项目共享的
MyBatis一级缓存存放的是对象,二级缓存存放的是对象的数据
所以要求二级缓存存放的POJO必须是可序列化的,也就是要实现Serializable接口
MyBatis二级缓存默认不开启,手动开启后数据先存放在一级缓存中,只有一级缓存数据清空后,数据才会存到二级缓存中

注:​SqlSession​调用 clearCache()​ 无法将数据存到二级缓存中(直接清空一级缓存的当前数据)

开启二级缓存

1. POJO类实现Serializable接口

public class User implements Serializable {private int id;private String username;private String sex;private String address;
}

2. 在MyBatis配置文件添加如下设置:

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

由于cacheEnabled默认值是true,所以该设置可以省略

3. 在映射文件(UserMapper.xml)添加<cache />​标签,该映射文件下的所有方法都支持二级缓存如果查询到的集合中对象过多,二级缓存只能缓存1024个对象引用。可以通过<cache />​标签的size属性修改该数量
<cache size="2048"/>

4. 测试二级缓存

@Test
public void testCache4() throws IOException {InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();SqlSessionFactory factory = builder.build(is);SqlSession session1 = factory.openSession();SqlSession session2 = factory.openSession();UserMapper mapper1 = session1.getMapper(UserMapper.class);UserMapper mapper2 = session2.getMapper(UserMapper.class);User user1 = mapper1.findById(1);System.out.println(user1);System.out.println(user1.hashCode());// 让一级缓存失效session1.commit();System.out.println("-------------------------------------------");User user2 = mapper2.findById(1);System.out.println(user2);System.out.println(user2.hashCode());
}

 4. 总结

对比项一级缓存(本地缓存)二级缓存(全局缓存)
存储位置SqlSession 的 Executor 中的 PerpetualCacheSqlSessionFactory
开启方式默认开启,无需配置默认不开启,需手动配置
共享范围仅同一 SqlSession 内共享同一 SqlSessionFactory 创建的 SqlSession 共享
存储内容完整对象对象数据(需 POJO 实现 Serializable 接口)
生效关键条件同一 SqlSession 执行相同 SQL一级缓存清空后,同一 SqlSessionFactory 下执行相同 SQL
核心清空场景SqlSession 调用 close ()/clearCache ()/commit ()、执行增删改操作对应增删改操作、配置失效等

 到此,缓存就讲解完了,希望对大家有所帮助(๑•̀ㅂ•́)و✧

http://www.lryc.cn/news/599332.html

相关文章:

  • “磁”力全开:钕铁硼重塑现代科技生活
  • 求职招聘小程序源码招聘小程序开发定制
  • 解密国密 SSL 证书:SM2、SM3、SM4 算法的协同安全效应
  • Spring Boot 接口安全设计:接口限流、防重放攻击、签名验证
  • SEC_FirePower 第二天作业
  • 软件异常读写威胁硬盘安全:从过往案例到防护之道
  • Linux运维新人自用笔记(Rsync远程传输备份,服务端、邮箱和客户端配置、脚本)
  • 网络资源模板--基于Android Studio 实现的天气预报App
  • Inception网络架构:深度学习视觉模型的里程碑
  • Java-Properties类和properties文件详解
  • android app适配Android 15可以在Android studio自带的模拟器上进行吗,还是说必须在真机上进行
  • 【Android Studio】安装Trae插件后Android Studio 启动崩溃问题处理
  • AR眼镜重塑外科手术导航:精准“透视”新突破
  • 深入理解 TCP 协议:从原理到实践的技术解析
  • 机器学习之knn算法保姆级教学
  • 扣子平台之提示词生成
  • 双指针算法介绍及使用(下)
  • 进阶向:基于Python的局域网聊天工具(端对端加密)
  • Amazon Bedrock中的Stability AI文本转图像模型:技术原理、应用实践与未来趋势
  • 创始人IP:知识变现的核心资产
  • RAG实战指南 Day 24:上下文构建与提示工程
  • winform表格DataGridView多个单元格批量输入数字
  • 瑞萨电子RA-T MCU系列新成员RA2T1——电机控制专家
  • MySQL性能优化配置终极指南
  • 详谈OSI七层模型和TCP/IP四层模型以及tcp与udp为什么是4层,http与https为什么是7层
  • Kotlin 数据容器 - List(List 概述、创建 List、List 核心特性、List 元素访问、List 遍历)
  • STM32与ADS1220实现多通道数据采集的完整分析和源程序
  • 【WPS】office邮件合并,怎么将数据源excel中的下一条拼接在文档中的下一个位置
  • 目标导向的强化学习:问题定义与 HER 算法详解—强化学习(19)
  • Android Kotlin 协程全面指南