当前位置: 首页 > 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.dtcms.com/a/298069.html

相关文章:

  • android JXL 导出Excel(.xls/xlsx)
  • 解决企业微信收集表没有图片、文件组件,不能收集图片的问题
  • windows 安排 openssl
  • 三、操作系统——第1章:计算机系统概述
  • 星痕共鸣 C++显示打出的攻击力
  • 【前端工程化】前端项目开发过程中如何做好通知管理?
  • AVL树和红黑树的特性以及模拟实现
  • 【CMake】CMake 与 C++ 协同:条件配置机制及控制台控制实例解析
  • [C++]string::substr
  • MindJourney:构建空间智能的新范式——VLM与视频扩散式世界模型的融合
  • 【LeetCode Solutions】LeetCode 热题 100 题解(16 ~ 20)
  • 【牛客网C语言刷题合集】(三)
  • 2025年-ClickHouse 高性能实时分析数据库(大纲版)
  • 【开发杂谈】用AI玩AI聊天游戏:使用 Electron 和 Python 开发大模型语音聊天软件
  • 如何搭建Linux环境下的flink本地集群
  • 【硬件-笔试面试题】硬件/电子工程师,笔试面试题-26,(知识点:硬件电路的调试方法:信号追踪,替换,分段调试)
  • 飞算 JavaAI “撤回接口信息” 功能:误删接口不用慌,一键恢复更省心
  • Linux 设备驱动模型
  • WINDOWS10系统重装软件篇
  • QML图形效果之阴影效果(DropShadow与InnerShadow)
  • Cacti命令执行漏洞分析(CVE-2022-46169)
  • compileSdkVersion和targetSdkVersion可以不一样的版本吗
  • 图论:并查集
  • 深入解析JVM垃圾回收调优:性能优化实践指南
  • Python 数据可视化之 Matplotlib 库
  • Java常用命令、JVM常用命令
  • RAG面试内容整理-3. 向量检索原理与常用库(ANN、FAISS、Milvus 等)
  • blender基本操作
  • flutter TextField 失去焦点事件
  • Qt:qRegisterMetaType函数使用介绍