MyBatis的一级缓存和二级缓存

MyBatis的一级缓存和二级缓存

  • [1. 一级缓存](#1. 一级缓存)
    • [1.1 是什么](#1.1 是什么)
    • [1.2 缓存命中的条件](#1.2 缓存命中的条件)
    • [1.3 我的测试](#1.3 我的测试)
  • [2. 二级缓存](#2. 二级缓存)

1. 一级缓存

1.1 是什么

🖊 MyBatis 一级缓存也叫「本地缓存」,是 SqlSession 级别的缓存(每个 SqlSession 有自己专属的一级缓存),默认自动开启,无需任何配置。

🖊 可以把它理解为:每个 SqlSession 都有一个 "专属口袋🎒",第一次查数据库拿到的数据会放进这个口袋,同一个 SqlSession 再查相同数据时,直接从口袋里拿,不用再问数据库要。

✏ 同一个 SqlSession 执行第一次查询:缓存中无数据 → 查数据库 → 结果存入一级缓存 → 返回数据

✏ 同一个 SqlSession 执行第二次相同查询:缓存中有数据 → 直接返回缓存数据(不查库)

✏ 当 SqlSession 执行增删改、提交(commit)、回滚(rollback)、关闭(close)时,一级缓存会被自动清空(避免缓存数据和数据库不一致)

1.2 缓存命中的条件

  • 一级缓存不是 "随便查都能用",必须满足以下所有条件,才会命中缓存:

🖊 SqlSession 相同: 不同 SqlSession 的缓存相互隔离(比如 SqlSession1 和 SqlSession2 各有自己的缓存,互不共享)

🖊 查询条件完全相同: SQL 语句、参数、分页 / 排序条件、行锁等完全一致(比如 select * from user where id=1 和 select * from user where id=2 是不同的缓存键)

🖊 Mapper 标识相同: 即 Mapper 的 namespace + SQL 的 id 相同(比如 com.user.mapper.UserMapper.selectById 这个唯一标识)

🖊 未执行清空缓存的操作: 比如增删改、commit、rollback 等

1.3 我的测试

java 复制代码
package com.jagochan.train.business.controller;

import com.jagochan.train.business.resp.TrainQueryResp;
import com.jagochan.train.business.service.TrainService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.TransactionStatus; 
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@Slf4j
@Tag(name = "测试控制器", description = "用于测试的控制器")
@RestController
@RequestMapping("/business/test")
public class SuccessController {

    @Resource
    private TrainService trainService;

    @Resource
    private TransactionTemplate transactionTemplate;

    @Operation(description = "测试MyBatis的一级缓存")
    @GetMapping("/testMyBatisLevelOneCache/{withTransaction}")
    public Object testMyBatisLevelOneCache(@PathVariable Boolean withTransaction) {
        if (withTransaction) {
            return transactionTemplate.execute(new TransactionCallback() { // 有事务
                @Override
                public Object doInTransaction(TransactionStatus status) {
                    try {
                        log.debug("😀第1次查询 with transaction");
                        List<TrainQueryResp> res1 = trainService.listAll();
                        log.debug("😀第2次查询 with transaction");
                        List<TrainQueryResp> res2 = trainService.listAll();
                        log.debug("😀finish with transaction");
                        return "res1💴" + res1;
                    } catch (Exception e) {
                        status.setRollbackOnly();
                        return false;
                    }
                }
            });
        } else {
            log.debug("😀第1次查询 without transaction");
            List<TrainQueryResp> res1 = trainService.listAll();
            log.debug("😀第2次查询 without transaction");
            List<TrainQueryResp> res2 = trainService.listAll();
            log.debug("😀finish without transaction");
            return "res2🍀" + res2;
        }
    } 
 
} 

🖊 当没有事务的时候:每一次查询都会查询数据库

🖊 当有 事务的时候:第二次查询缓存命中


❓ 关闭一级缓存

🖊 在配置文件中增加如下配置

yml 复制代码
mybatis:
  configuration:
    local-cache-scope: statement # 默认是session

2. 二级缓存

✏ MyBatis 二级缓存是 Mapper/Namespace 级 全局缓存,默认关闭,需手动配置

✏ 开启条件:全局 ① cacheEnabled=true;② Mapper 加 <cache/>;③ 实体类序列化

✏ 数据同步:SqlSession 提交 / 关闭时,将一级缓存数据同步到二级缓存

✏ 核心特点:多 SqlSession 共享,增删改自动清空,默认内存存储

✏ 适用场景:单机 + 只读 / 少写数据

相关推荐
一枕槐安4877 小时前
RAG 服务扛住高并发:缓存、队列、限流三件套
java·spring·缓存·异步任务·rag·断路器
与数据交流的路上15 小时前
一次 redis 幽灵内存的分析
数据库·redis·缓存
正儿八经的少年15 小时前
MyBatis 一对一、一对多 SQL
数据库·sql·mybatis
Geek-Chow15 小时前
06 · DeepSeek V4.1 Flash 推理端到端走查:一个 Agent 请求穿过 recipe、KV 缓存、Prefill 与 Decode
缓存
前进的李工16 小时前
Agent 学习笔记 04:KV Cache 与上下文缓存
笔记·学习·缓存·agent·注意力机制·kv cache·prompt cache
John_Hui1 天前
第 5 篇:Ubuntu 安装 Redis
数据库·redis·缓存
l1t1 天前
DeepSeek总结的ALTER FUNCTION SET work_mem:无需全局更改即可修复 PostgreSQL 磁盘溢出
sql·缓存·postgresql
咖啡八杯1 天前
Redis 工具封装:RedisCache 对 Operations 体系的二次封装
java·数据库·redis·缓存·框架·springboot·若依
paopaokaka_luck2 天前
社区服务平台(加权协同过滤推荐、Jieba中文词频分析、WebSocket实时聊天、求助处理闭环、 活动积分闭环、ECharts多维分析)
java·前端·spring boot·mysql·echarts·mybatis