Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >十、MyBatis的缓存

十、MyBatis的缓存

原创
作者头像
刘大猫
发布于 2025-02-25 15:11:42
发布于 2025-02-25 15:11:42
510
举报
文章被收录于专栏:JAVA相关JAVA相关

@toc

十、MyBatis的缓存

10.1 MyBatis的一级缓存

一级缓存是SqlSession级别的,通过同一个SqlSession查询的数据会被缓存,下次查询相同的数据,就会从缓存中直接获取,不会从数据库重新访问使一级缓存。

一级缓存失效的四种情况

1) 不同的SqlSession对应不同的一级缓存

2) 同一个SqlSession但是查询条件不同

3) 同一个SqlSession两次查询期间执行了任何一次增删改操作

4) 同一个SqlSession两次查询期间手动清空了缓存

场景1:判断同一个sqlSession是否查询1级缓存,答案:会查询1级缓存

代码语言:java
AI代码解释
复制
@Test

public void testCache1(){

        SqlSession sqlSession = SqlSessionUtils.getSqlSession();

        CacheMapper cacheMapper1 = sqlSession.getMapper(CacheMapper.class);

        System.out.println(cacheMapper1.getAddressByUserId(1));

        CacheMapper cacheMapper2 = sqlSession.getMapper(CacheMapper.class);

        System.out.println(cacheMapper2.getAddressByUserId(1));

    }

结果日志打印:

场景2:判断不同sqlSession是否查询1级缓存,答案:不会查询1级缓存

代码语言:java
AI代码解释
复制
@Test

public void testCache2(){

        SqlSession sqlSession1 = SqlSessionUtils.getSqlSession();

        CacheMapper cacheMapper1 = sqlSession1.getMapper(CacheMapper.class);

        System.out.println(cacheMapper1.getAddressByUserId(1));

        SqlSession sqlSession2 = SqlSessionUtils.getSqlSession();

        CacheMapper cacheMapper2 = sqlSession2.getMapper(CacheMapper.class);

        System.out.println(cacheMapper2.getAddressByUserId(1));

    }

结果日志打印:

场景3:判断相同sqlSession中间执行一次清除后,是否查询1级缓存,答案:不会查询1级缓存

代码语言:java
AI代码解释
复制
@Test

public void testCache3(){

        SqlSession sqlSession = SqlSessionUtils.getSqlSession();

        CacheMapper cacheMapper = sqlSession.getMapper(CacheMapper.class);

        System.out.println(cacheMapper.getAddressByUserId(1));

        sqlSession.clearCache();

        System.out.println(cacheMapper.getAddressByUserId(1));

    }

结果日志打印:

10.2 MyBatis的二级缓存

二级缓存是SqlSessionFactory级别,通过同一个SqlSessionFactory创建的SqlSession查询的结果会被缓存;此后若再次执行相同的查询语句,结果就会从缓存中获取

二级缓存开启的条件

  1. 在核心配置文件中,设置全局配置属性cacheEnabled="true",默认为true,不需要设置
  2. 在映射文件中设置标签\<cache />
代码语言:java
AI代码解释
复制
<mapper namespace="com.mybatis.mapper.CacheMapper">

    <cache/>    

</mapper>
  1. 二级缓存必须在SqlSession关闭或提交之后有效
  2. 查询的数据所转换的实体类类型必须实现序列化的接口
代码语言:java
AI代码解释
复制
@Data

@AllArgsConstructor

@NoArgsConstructor

@ToString

public class Address implements Serializable {

    //id

    private Integer id;

    //用户名称

    private String name;

    //用户ID

    private Integer userId;



    private List<User> userList = new ArrayList<>();

}

使二级缓存失效的情况:两次查询之间执行了任意的增删改,会使一级和二级缓存同时失效。

场景1:验证二级缓存生效的问题,结论:没有SqlSession关闭或提交之后缓存开启不生效

代码语言:java
AI代码解释
复制
@Test

public void testCache4(){

        try {

            InputStream is = Resources.getResourceAsStream("mybatis-config.xml");

            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);

            SqlSession sqlSession1 = sqlSessionFactory.openSession(true);

            CacheMapper mapper1 = sqlSession1.getMapper(CacheMapper.class);

            System.out.println(mapper1.getAddressByUserId(1));

            SqlSession sqlSession2 = sqlSessionFactory.openSession(true);

            CacheMapper mapper2 = sqlSession2.getMapper(CacheMapper.class);

            System.out.println(mapper2.getAddressByUserId(1));

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

结果日志打印:

执行sqlSession1.close();之后验证效果,如图

代码语言:java
AI代码解释
复制
@Test

public void testCache4(){

        try {

            InputStream is = Resources.getResourceAsStream("mybatis-config.xml");

            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);

            SqlSession sqlSession1 = sqlSessionFactory.openSession(true);

            CacheMapper mapper1 = sqlSession1.getMapper(CacheMapper.class);

            System.out.println(mapper1.getAddressByUserId(1));

            sqlSession1.close();

            SqlSession sqlSession2 = sqlSessionFactory.openSession(true);

            CacheMapper mapper2 = sqlSession2.getMapper(CacheMapper.class);

            System.out.println(mapper2.getAddressByUserId(1));

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

结果日志打印:

10.3 二级缓存的相关配置

MyBatis缓存查询的顺序

  • 先查询二级缓存,因为二级缓存中可能会有其他程序已经查出来的数据,可以拿来直接使用。
  • 如果二级缓存没有命中,再查询一级缓存
  • 如果一级缓存也没有命中,则查询数据库
  • SqlSession关闭之后,一级缓存中的数据会写入二级缓存

10.4 整合第三方缓存EHCache

问题:为啥需要使用第三方缓存插件,而不是完全直接使用Mybatis自带的缓存?

答案:Mybatis自带的缓存是持久层框架,会把缓存写入磁盘中,而读写磁盘肯定会涉及大量的IO操作,明显会导致效率低,如果能从内存中读取缓存内容那就会快很多,所以需要使用第三方缓存插件。

注意:第三方缓存插件代替的只是“二级缓存”而已,无法代替一级缓存。

  • 1.添加依赖
代码语言:java
AI代码解释
复制
<!-- Mybatis EHCache整合包 -->

<dependency>

    <groupId>org.mybatis.caches</groupId>

    <artifactId>mybatis-ehcache</artifactId>

    <version>1.2.1</version>

</dependency>

<!-- slf4j日志门面的一个具体实现 -->

<dependency>

    <groupId>ch.qos.logback</groupId>

    <artifactId>logback-classic</artifactId>

    <version>1.2.3</version>

</dependency>
  • 2.各jar包功能
  • 3.创建EHCache的配置文件ehcache.xml
代码语言:java
AI代码解释
复制
<?xml version="1.0" encoding="utf-8" ?>

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

         xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">

    <!-- 磁盘保存路径 -->

    <diskStore path="D:\atguigu\ehcache"/>

    <defaultCache

            maxElementsInMemory="1000"

            maxElementsOnDisk="10000000"

            eternal="false"

            overflowToDisk="true"

            timeToIdleSeconds="120"

            timeToLiveSeconds="120"

            diskExpiryThreadIntervalSeconds="120"

            memoryStoreEvictionPolicy="LRU">

    </defaultCache>

</ehcache>
  • 4.设置二级缓存的类型
代码语言:java
AI代码解释
复制
<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
  • 5.EHCache配置文件说明

本人其他相关文章链接

1.一、MyBatis简介:MyBatis历史、MyBatis特性、和其它持久化层技术对比、Mybatis下载依赖包流程

2.二、搭建MyBatis采用xml方式,验证CRUD(增删改查操作)

3.三、MyBatis核心配置文件详解

4.四、MyBatis获取参数值的两种方式(重点)

5.五、MyBatis的增删改查模板(参数形式包括:String、对象、集合、数组、Map)

6.六、MyBatis特殊的SQL:模糊查询、动态设置表名、校验名称唯一性

7.七、MyBatis自定义映射resultMap

8.八、(了解即可)MyBatis懒加载(或者叫延迟加载)

9.九、MyBatis动态SQL

10.十、MyBatis的缓存

11.十一、MyBatis的逆向工程

12.十二、MyBatis分页插件

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
【愚公系列】2023年10月 Java教学课程 115-Mybatis(缓存)
数据库查询缓存是指在数据库系统中,针对一些常被查询的结果,将其缓存到内存中,以减少对数据库的查询请求,从而提高数据库查询效率的一种技术。
愚公搬代码
2025/05/28
810
【MyBatis框架点滴】——MyBatis二级缓存
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/huyuyang6688/article/details/51770863
DannyHoo
2018/09/13
3400
【MyBatis框架点滴】——MyBatis二级缓存
图解 | 聊聊 MyBatis 缓存
MappedStatement:代表要发往数据库执行的指令,可以理解为是 SQL 的抽象表示。
悟空聊架构
2022/12/12
2650
图解 | 聊聊 MyBatis 缓存
全网最全MyBatis基于XML使用系列四:缓存
当用户多次查询相同的数据的时候,如果不需要缓存,那么每次都需要访问数据库,从而增加数据库的压力,当使用缓存之后,第一次将这些数据从数据库中查询,将查询的数据保存到缓存中,当用户再次查询相同的数据时,不用直接访问数据库进行查询,直接取缓存里面查询。这样可以减少网络连接和数据库查询带来的损耗,提高代码的查询效率,减少高并发访问带来的系统性能问题。
玖柒的小窝
2021/12/10
2390
全网最全MyBatis基于XML使用系列四:缓存
面试题:MyBatis二级缓存[通俗易懂]
①、一级缓存是SqlSession级别的缓存。在操作数据库时需要构造sqlSession对象,在对象中有一个数据结构(HashMap)用于存储缓存数据。不同的sqlSession之间的缓存数据区域(HashMap)是互相不影响的。
全栈程序员站长
2022/09/29
7820
面试题:MyBatis二级缓存[通俗易懂]
Data Access 之 MyBatis(五)- MyBatis Cache
MyBatis包含一个非常强大的查询缓存特性,可以非常方便的配置和定义。缓存可以极大的提高查询效率
RiemannHypothesis
2022/08/19
3460
Data Access 之 MyBatis(五)-  MyBatis Cache
【MyBatis学习13】MyBatis中的二级缓存[通俗易懂]
前面介绍了,mybatis中的二级缓存是mapper级别的缓存,值得注意的是,不同的mapper都有一个二级缓存,也就是说,不同的mapper之间的二级缓存是互不影响的。为了更加清楚的描述二级缓存,先来看一个示意图:
全栈程序员站长
2022/09/29
1.5K0
【MyBatis学习13】MyBatis中的二级缓存[通俗易懂]
mybatis 高级映射和spring整合之查询缓存(5)
mybatis 高级映射和spring整合之查询缓存(5) 2.0 查询缓存 2.0.1 什么是查询缓存 mybatis提供缓存,用于减轻数据压力,提高数据库性能。 mybatis提供一级缓存和二级缓存。 一级缓存是SqlSession级别的缓存: 在操作数据库时需要购造sqlSession对象,在对象中有一个数据结构(HashMap)用于存储缓存数据。 不同的sqlSession之间的缓存数据区域(HashMap)是互不影响的。
王小雷
2019/05/26
4720
一文彻底读懂优秀开源产品MyBatis一级缓存设计!
缓存是 MyBatis 中非常重要的特性。合理使用缓存能够减少数据库 IO,显著提升系统性能。但是在分布式环境下,如果使用不当,则可能会带来数据一致性问题。MyBatis 提供了一级缓存和二级缓存,其中一级缓存基于 SqlSession 实现,而二级缓存基于 Mapper,本文将会详细讲解一级缓存。
玄姐谈AGI
2020/11/09
5461
一文彻底读懂优秀开源产品MyBatis一级缓存设计!
mybatis 详解(九)------ 一级缓存、二级缓存
  上一章节,我们讲解了通过mybatis的懒加载来提高查询效率,那么除了懒加载,还有什么方法能提高查询效率呢?这就是我们本章讲的缓存。   本篇源码下载链接:http://pan.baidu.com
IT可乐
2018/01/04
9760
mybatis 详解(九)------ 一级缓存、二级缓存
《从Java面试题来看源码》,项目中使用 Mybatis 缓存吗?为什么项目中不用 Mybatis 的二级缓存?
答:MyBatis 的二级缓存相对于一级缓存来说,实现了 SqlSession 之间缓存数据的共享,同时粒度更加的细,能够到 namespace 级别,通过 Cache 接口实现类不同的组合,对 Cache 的可控性也更强。 但 MyBatis 在多表查询时,极大可能会出现脏数据,有设计上的缺陷,安全使用二级缓存的条件比较苛刻。 在分布式环境下,由于默认的 MyBatis Cache 实现都是基于本地的,分布式环境下必然会出现读取到脏数据,需要使用集中式缓存将 MyBatis 的 Cache 接口实现,有一定的开发成本,直接使用 Redis,Memcached 等分布式缓存可能成本更低,安全性也更高。
阿提说说
2022/12/02
4560
Mybatis的缓存机制详解
MyBatis 包含了一个非常强大的查询缓存特性,它可以非常方便地配置和定制。MyBatis 3 中的缓存实现的很多改进都已经实现了,使得它更加强大而且易于配置。mybatis默认情况下只会开启一级缓存,也就是局部的 session 会话缓存。
端碗吹水
2020/09/23
7160
Mybatis的缓存机制详解
MyBatis缓存机制详解
MyBatis作为目前最常用的ORM数据库访问持久层框架,其本身支持动态SQL存储映射等高级特性也非常优秀,通过Mapper文件采用动态代理模式使SQL与业务代码相解耦,日常开发中使用也非常广泛,本文主要讨论mybatis缓存功能,mybatis缓存本身设计初衷是为了解决同一会话相同查询的效率问题,单机环境下也确实起到了提高查询效率的作用,但是随着业务场景变化以及分布式微服务的出现,其弊端也渐渐显现出来,不同会话间操作数据,关联查询数据采用mybatis缓存时会存在出现脏数据的风险。
全栈程序员站长
2022/08/26
6190
MyBatis缓存机制详解
MyBatis--注解、缓存配置、其他工具
前面熟悉了MyBatis的基本使用,针对一些简单的sql语句,如对一张表的增删改查,可以使用MyBatis提供的注解,省去写映射文件的步骤,复杂的多表查询,还是建议使用映射文件的方式
aruba
2022/05/18
3240
MyBatis--注解、缓存配置、其他工具
mybatis框架一级和二级缓存
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
多凡
2019/11/01
4880
MyBatis:缓存,延迟加载,注解应用
实际开发过程中很多时候并不需要总是在加载用户信息时就一定要加载他的订单信息。此时就是我们所说的延迟加载。
RendaZhang
2020/09/08
9320
MyBatis:缓存,延迟加载,注解应用
mybatis 缓存的使用, 看这篇就够了「建议收藏」
缓存的重要性是不言而喻的。 使用缓存, 我们可以避免频繁的与数据库进行交互, 尤其是在查询越多、缓存命中率越高的情况下, 使用缓存对性能的提高更明显。
全栈程序员站长
2022/08/31
4810
mybatis 缓存的使用, 看这篇就够了「建议收藏」
Mybatis的一级缓存与二级缓存
我们都知道缓存,缓存的作用也都是非常的明显,为了减轻数据库的压力,有些时候查询数据的时候,会把数据存入到缓存中,等接下来相同的请求查询数据时,直接从缓存中获取数据,不用再去访问数据库了,而合理使用缓存是优化中最常见的,避免频繁操作数据库,减轻数据库的压力,同时提高系统性能。
Java极客技术
2023/10/25
3890
Mybatis的一级缓存与二级缓存
MyBatis框架:第十章:mybatis缓存
mybatis缓存 说明: 缓存指的是把一些常用的数据,保存到一个可以高速读取的缓冲区中。方便程序在频繁读取的时候,可以快速的取出数据。这就叫做缓存。
Java廖志伟
2022/09/28
2800
MyBatis框架:第十章:mybatis缓存
聊聊MyBatis缓存机制
前言 MyBatis是常见的Java数据库访问层框架。在日常工作中,开发人员多数情况下是使用MyBatis的默认缓存配置,但是MyBatis缓存机制有一些不足之处,在使用中容易引起脏数据,形成一些潜在的隐患。 个人在业务开发中也处理过一些由于MyBatis缓存引发的开发问题,带着个人的兴趣,希望从应用及源码的角度为读者梳理MyBatis缓存机制。 本次分析中涉及到的代码和数据库表均放在GitHub上,地址: mybatis-cache-demo 。 目录 本文按照以下顺序展开。 一级缓存介绍及相关配置。
美团技术团队
2018/03/13
1.6K0
聊聊MyBatis缓存机制
推荐阅读
相关推荐
【愚公系列】2023年10月 Java教学课程 115-Mybatis(缓存)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档