MyBatis 之缓存机制核心解析

简介: 本文由艺杯羹撰写,系统讲解MyBatis缓存机制:一级缓存(SqlSession级、默认开启、存对象)与二级缓存(Mapper级、需手动配置、存序列化数据),涵盖原理、配置、清空时机及适用场景,助力高效开发。

前言

大家好,我是艺杯羹(๑•̀ㅂ•́)و✧
本文来讲解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)添加标签,该映射文件下的所有方法都支持二级缓存如果查询到的集合中对象过多,二级缓存只能缓存1024个对象引用。可以通过标签的size属性修改该数量  

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 中的 PerpetualCache

SqlSessionFactory

开启方式

默认开启,无需配置

默认不开启,需手动配置

共享范围

仅同一 SqlSession 内共享

同一 SqlSessionFactory 创建的 SqlSession 共享

存储内容

完整对象

对象数据(需 POJO 实现 Serializable 接口)

生效关键条件

同一 SqlSession 执行相同 SQL

一级缓存清空后,同一 SqlSessionFactory 下执行相同 SQL

核心清空场景

SqlSession 调用 close ()/clearCache ()/commit ()、执行增删改操作

对应增删改操作、配置失效等

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

目录
相关文章
|
2月前
|
Java 程序员 应用服务中间件
Maven之初识与安装
本文详解Maven安装与配置全流程:从基础概念、下载安装、环境变量配置到版本验证,助新手一次理清逻辑、顺利完成部署;涵盖一键构建、依赖管理核心功能,并提供交流支持。
190 0
Maven之初识与安装
|
2月前
|
Java 应用服务中间件 数据库连接
Maven 之工程化开发核心指南:插件配置、pom 文件与依赖管理
本文详解Maven工程化开发核心:从IDEA中Maven插件配置、Web项目创建与目录结构搭建,到pom.xml关键配置(坐标、properties、dependencies、plugins)、依赖范围(provided等)原理与实战,助你掌握工程化思维,高效构建Java项目。(239字)
108 1
Maven 之工程化开发核心指南:插件配置、pom 文件与依赖管理
|
2月前
|
SQL 安全 Java
MyBatis 动态 SQL:让 SQL 语句随条件灵活变化
本文详解MyBatis动态SQL核心标签:`&lt;if&gt;`条件判断、`&lt;where&gt;`智能拼接、`&lt;set&gt;`安全更新、`&lt;choose&gt;`多选一、`&lt;foreach&gt;`遍历集合,结合代码与图示,助你告别硬编码,一个方法搞定多条件查询与批量操作。(239字)
127 0
MyBatis 动态 SQL:让 SQL 语句随条件灵活变化
|
2月前
|
XML 运维 Java
Tomcat 核心配置解析:4 大文件、乱码处理、端口与 Manager 配置
本文详解Tomcat四大核心配置文件(context.xml、web.xml、server.xml、tomcat-users.xml)功能与配置要点,涵盖控制台乱码解决、端口修改、Manager管理界面启用及用户权限配置,助你扎实掌握Tomcat运维关键技能。
159 0
Tomcat 核心配置解析:4 大文件、乱码处理、端口与 Manager 配置
|
2月前
|
C语言 数据安全/隐私保护
二级C语言题解:二维数组每行最大值与首元素交换、删除结构体的重复项、取出单词首字母
本教程专为C语言二级考生、中职学生及编程初学者设计,涵盖三大核心题型:二维数组每行最大值与首元素交换、结构体重复项删除(保留首个)、字符串单词首字母提取。含详细分析、易错点解析与标准代码,助你夯实基础、提升解题思维。
104 2
二级C语言题解:二维数组每行最大值与首元素交换、删除结构体的重复项、取出单词首字母
|
2月前
|
人工智能 C语言
二级C语言题解:十进制转其他进制、非素数求和、重复数统计
本文详解三类经典编程题:十进制转任意进制(填空)、非素数求和(修改)与重复数字统计(设计),含完整代码、逐空分析及易错点解析,助你夯实C语言基础。
136 2
二级C语言题解:十进制转其他进制、非素数求和、重复数统计
|
2月前
|
存储 C语言
二级C语言题解:整数序列奇偶个数、拼接数字字符、数组取偶数并加小数点
本文详解C语言三道经典编程题:①统计整数序列中奇偶数个数并返回结构体;②提取字符串中数字字符拼接成整数;③筛选数组偶数并按原序拼接为“数字.”格式字符串。含完整代码、填空/修改/设计解析及易错点提醒。
105 1
二级C语言题解:整数序列奇偶个数、拼接数字字符、数组取偶数并加小数点
|
2月前
|
机器学习/深度学习 算法 C语言
二级C语言题解:矩阵主、反对角线元素之和,二分法求方程根,处理字符串中 * 号
本文详解三道C语言编程题:①矩阵主/反对角线元素求和(填空);②二分法求方程根(修改错误);③删除字符串中间的“*”号(程序设计)。含题目分析、易错点解析与完整代码,助力算法与指针实践能力提升。
95 1
二级C语言题解:矩阵主、反对角线元素之和,二分法求方程根,处理字符串中 * 号
|
2月前
|
Java 应用服务中间件 Shell
Tomcat 使用与配置全解
Tomcat是Apache开源的轻量级Java Web容器,实现Servlet/JSP规范,支持Web应用部署与运行。需搭配JDK使用,目录结构清晰(如webapps存应用、conf存配置),默认端口8080,启动简单,广泛用于开发与中小型项目部署。
153 1
Tomcat 使用与配置全解
|
2月前
|
SQL Java 数据库连接
MyBatis 之基础概念与框架原理详解
MyBatis是一款轻量级半自动ORM框架,封装JDBC,让开发者专注SQL编写与业务逻辑;支持XML/注解配置、动态SQL、高级映射,SQL与代码分离,灵活高效,显著提升持久层开发效率。(239字)
133 1
MyBatis 之基础概念与框架原理详解

热门文章

最新文章