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 共享,增删改自动清空,默认内存存储

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

相关推荐
知我Deja_Vu7 天前
redisCommonHelper.generateCode(“GROUP“),Redis 生成码方法
数据库·redis·缓存
莫寒清7 天前
Mybatis的插件原理
面试·mybatis
没有bug.的程序员7 天前
电商秒杀系统深度进阶:高并发流量建模、库存零超卖内核与 Redis+MQ 闭环
数据库·redis·缓存·高并发·电商秒杀·流量建模·库存零超卖
troublea7 天前
ThinkPHP3.x高效学习指南
mysql·nginx·缓存
troublea7 天前
ThinkPHP6快速入门指南
数据库·mysql·缓存
莫寒清7 天前
MyBatis 中动态 SQL 的作用
面试·mybatis
Emotional。7 天前
AI Agent 性能优化和成本控制
人工智能·深度学习·机器学习·缓存·性能优化
吹晚风吧7 天前
实现一个mybatis插件,方便在开发中清楚的看出sql的执行及执行耗时
java·sql·mybatis
码云数智-大飞7 天前
像写 SQL 一样搜索:dbVisitor 如何用 MyBatis 范式颠覆 ElasticSearch 开发
sql·elasticsearch·mybatis
jnrjian7 天前
Oracle 共享池 库缓存下的 Library Cache Lock
数据库·缓存·oracle