mybatis的一级缓存和二级缓存

MyBatis一级缓存和二级缓存 Mybatis缓存 阅读详情

一级缓存

首先做一个测试,创建一个mapper配置文件和mapper接口,我这里用了最简单的查询来演示。

<mapper namespace="cn.elinzhou.mybatisTest.mapper.UserMapper">

    <select id="findUsers" resultType="cn.elinzhou.mybatisTest.pojo.User">
        SELECT * FROM user
    </select>
</mapper>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
public interface UserMapper {
    List<User> findUsers()throws Exception;
}
  • 1
  • 2
  • 3

然后编写一个单元测试

public class UserMapperTest {


    SqlSession sqlSession = null;
    @Before
    public void setUp() throws Exception {
        // 通过配置文件获取数据库连接信息
        Reader reader = Resources.getResourceAsReader("cn/elinzhou/mybatisTest/config/mybatis.xml");
        // 通过配置信息构建一个SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
        // 通过sqlSessionFactory打开一个数据库会话
        sqlSession = sqlSessionFactory.openSession();
    }

    @Test
    public void testFindUsers() throws Exception {
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<User> users = userMapper.findUsers();
        System.out.println(users);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

运行,可以看到控制台输出(先配好log4j)为类似如下图日志 
这里写图片描述

日志说明了该操作执行的sql语句已经查询的内容,最后一行是我手动通过System.out.printf输出的结果。

然后再加一条语句

users = userMapper.findUsers();
  • 1

之前的单元测试就变成了这个样子

这里写图片描述

也就是在执行完userMapper.findUsers();后立刻再执行一遍userMapper.findUsers(); 可以想象,其实这两个操作执行的sql是完全相同的,而且在这期间没有对数据库进行过其他操作。然后执行该单元测试,发现效果跟上面执行一条的时候完全相同,也就是执行第二次userMapper.findUsers();操作的时候没有对数据库进行查询,那么得到的数据是从哪里来的?答案是一级缓存。

mybatis一级缓存是指在内存中开辟一块区域,用来保存用户对数据库的操作信息(sql)和数据库返回的数据,如果下一次用户再执行相同的请求,那么直接从内存中读数数据而不是从数据库读取。 
其中数据的生命周期有两个影响因素。

  1. 对sqlsession执行commit操作时

对sqlsession执行commit操作,也就意味着用户执行了update、delete等操作,那么数据库中的数据势必会发生变化,如果用户请求数据仍然使用之前内存中的数据,那么将读到脏数据。所以在执行sqlsession操作后,会清除保存数据的HashMap,用户在发起查询请求时就会重新读取数据并放入一级缓存中了。

这里写图片描述

这里写图片描述

上述测试就是在第一查询完后执行了commit操作,再进行查询。与之前的测试不同的是,这次测试控制台打印了两组查询结果,说明在commit之后mybatis对数据重新进行了查询。

  1. 关闭sqlsession

一般在mybatis集成spring时,会把SqlSessionFactory设置为单例注入到IOC容器中,不把sqlsession也设置为单例的原因是sqlsession是线程不安全的,所以不能为单例。那也就意味着其实是有关闭sqlsession的过程的。其实,对于每一个service中的sqlsession是不同的,这是通过mybatis-spring中的org.mybatis.spring.mapper.MapperScannerConfigurer创建sqlsession自动注入到service中的。 
而一级缓存的设计是每个sqlsession单独使用一个缓存空间,不同的sqlsession是不能互相访问数据的。当然,在sqlsession关闭后,其中数据自然被清空。

特此警告!!!! 
当MyBatis与spring整合后,如果没有事务,一级缓存是失效的!一级缓存是失效的!一级缓存是失效的!
原因就是两者结合后,sqlsession如果发现当前没有事务,那么每执行一个mapper方法,sqlsession就被关闭了。如果需要维持一级缓存的可用性,有两种途径:

  1. 添加事务
  2. 使用二级缓存

二级缓存

在使用二级缓存之前,先测试之前提到过的关闭sqlsession后会清空缓存的问题,把junit代码修改一下

@Test
    public void testFindUsers() throws Exception {
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<User> users = userMapper.findUsers();
        //关闭sqlsession
        sqlSession.close();

        //通过sqlsessionFactroy创建一个新的sqlsession
        sqlSession = sqlSessionFactory.openSession();
        //获取mapper对象
        userMapper = sqlSession.getMapper(UserMapper.class);
        users = userMapper.findUsers();
        System.out.println(users);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

这段代码在第一次查询完后关闭sqlsession,然后创建新的sqlsession和mapper来重新执行一次查询操作,可以预见,执行结果如图

这里写图片描述

说明关闭了sqlsession后的确把之前的缓存数据清空了,之后再执行同样的查询操作也会再访问一遍数据库。为了解决这个问题,需要使用二级缓存

一级缓存的作用域仅限于一个sqlsession,但是二级缓存的作用域是一个namespace。但并不是意味着同一个namespace创建的mapper可以互相读取缓存内容,这里的原则是,如果开启了二级缓存,那么在关闭sqlsession后,会把该sqlsession一级缓存中的数据添加到namespace的二级缓存中。

接下测试,先需要开启二级缓存。

1.打开二级缓存总开关 
打开总开关,只需要在mybatis总配置文件中加入一行设置

<settings>
   <!--开启二级缓存-->
    <setting name="cacheEnabled" value="true"/>
</settings>
  • 1
  • 2
  • 3
  • 4

2.打开需要使用二级缓存的mapper的开关

在需要开启二级缓存的mapper.xml中加入caceh标签

<cache/>
  • 1

3.POJO序列化

让需要使用二级缓存的POJO类实现Serializable接口,如

public class User implements Serializable {
  • 1

通过之前三步操作就可以使用二级缓存了,接下来测试。添加一个Junit方法

@Test
    public void testFindUsersCache() throws Exception {
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<User> users = userMapper.findUsers();
        //关闭sqlsession
        sqlSession.close();

        //通过sqlsessionFactroy创建一个新的sqlsession
        sqlSession = sqlSessionFactory.openSession();
        //获取mapper对象
        userMapper = sqlSession.getMapper(UserMapper.class);
        users = userMapper.findUsers();
        System.out.println(users);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

执行后可以发现,控制台值输出了一次查询过程,也可以证明二级缓存开启成功。

还有一个问题,之前说了,即使开启了二级缓存,不同的sqlsession之间的缓存数据也不是想互访就能互访的,必须等到sqlsession关闭了以后,才会把其一级缓存中的数据写入二级缓存。为了测试这个,把上述代码中的

sqlSession.close();
  • 1

注释,那么之前的代码就变成了 
这里写图片描述

再执行,发现控制太又输出了两次的查询过程,所以可以印证,只有关闭了sqlsession之后,才会把其中一级缓存数据写入二级缓存。

缓存配置

  • 关闭刷新

在默认情况下,当sqlsession执行commit后会刷新缓存,但是也可以强制设置为不刷新,在不需要刷新的标签中加入

flushCache="false" 
  • 1

如

<select id="findUsers" resultType="cn.elinzhou.mybatisTest.pojo.User" flushCache="false">
  • 1

那么,无论是否执行commit,缓存都不会刷新了。但是这样会造成脏读,只有在特殊情况下才使用

  • 自动刷新

有些情况下,需要设置自动刷新缓存,那么需要配置对应mapper中的cache标签。

flushInterval="10000"
  • 1

该属性表示每隔10秒钟自动刷新一遍缓存

Vivado新手必看:5分钟搞定FPGA程序固化到Flash(附MCS文件生成全流程) 本文为FPGA新手详细解析了如何将程序固化到Flash存储器的完整流程。核心在于理解SRAM工艺FPGA断电易失的特性,并利用Vivado工具将比特流文件转换为Flash可识别的MCS文件。文章重点拆解了生成MCS文件的关键配置步骤、硬件连接要点,以及通过JTAG烧写Flash的实战操作,并提供了常见启动失败问题的排查清单,帮助开发者实现设计从调试到产品部署的关键跨越。 阅读详情

相关推荐

Autowired的使用介绍

我们都知道在spring中@Autowired注解,是用来自动装配对象的。@Service@Autowired没错,这样是能够装配成功的,因为默认情况下spring是按照类型装配的,也就是我们所说的byType方式。此外,@Autowired注解的required。

白话机器学习 1350

Mybatis 之 二级缓存

⼆级缓存的原理和⼀级缓存原理⼀样,第⼀次查询,会将数据放⼊缓存中,然后第⼆次查询则会直接去 缓存中取。但是⼀级缓存是基于sqlSession的,⽽⼆级缓存是基于mapper⽂件的namespace的,也 就是说多个sqlSession可以共享⼀个mapper中的⼆级缓存区域,并且如果两个mapper的namespace 相同,即使是两个mapper,那么这两个mapper中执⾏sql查询到的数据也将存在相同的⼆级缓存区域 中如何使⽤⼆级缓存和⼀级缓存默认开启不⼀样,⼆级缓存需要我们⼿动开启⾸先在全局配置⽂件

凉茶铺的博客 1万+

Zemax显微镜设计:从物镜到目镜的完整光学系统优化

本文详细介绍了使用Zemax进行显微镜光学系统设计的完整流程,从物镜到目镜的优化技巧。通过实战案例和关键参数设置,帮助读者掌握数值孔径、视场角等核心概念,实现高分辨率显微镜设计。文章特别强调了系统级优化和公差分析的重要性,为科研和工业检测提供可靠的光学解决方案。

weixin_42549451的博客 439

Mybatis二级缓存详解

Mybatis二级缓存详解

汤键的博客 3003

大疆 DJI Mobile SDK实战指南——从零构建Android示例开发环境

本文提供了一份详尽的DJI Mobile SDK Android开发环境搭建实战指南。文章手把手教你从注册开发者账号、获取App Key,到配置Android Studio、下载官方示例代码,最终成功运行DJI官方Android示例程序,帮助开发者快速入门无人机应用开发,避开常见编译与依赖问题。

weixin_29188043的博客 275

SeedVR2插件双版本共存实战:手把手教你创建幽灵节点解决ComfyUI兼容问题

本文详细介绍了解决ComfyUI中SeedVR2插件新旧版本兼容问题的实战方案。通过目录隔离实现双版本共存,并手把手教你创建‘幽灵节点’来模拟缺失的SeedVR2ExtraArgs节点,从而让旧工作流得以正常运行,同时享受新版本的功能与性能。

red88的博客 1407

Mybatis二级缓存

mybatis二级缓存

jiayoubaobei2的博客 2765

新手必看:用FileZilla从武大IGS中心下载GNSS数据,再到crx2rnx转换的完整流程

本文详细介绍了新手如何通过FileZilla从武汉大学IGS中心下载GNSS数据,并使用crx2rnx工具将数据转换为RINEX格式的完整流程。涵盖工具准备、FTP连接、文件解压、格式转换及常见问题排查,帮助测绘和地信专业人员高效处理GNSS观测值数据。

weixin_29292431的博客 427

mybatis二级缓存

1、一级缓存:(本地缓存):sqlSession级别的缓存。在select标签中默认flushCache=false:不清缓存,如果改为true,每次查完就会清缓存。3)、每个增删改标签:flushCache=“true”:增删改执行完成后就会清除缓存(一级二级都会清除)5)、在全局配置文件的settings标签中localCacheScope:本地缓存作用域:(一级缓存。只有会话提交或者关闭以后,一级缓存中的数据才会转移到二级缓存中。1、一个会话,查询一条数据,这个数据就会被放在当前会话的一级缓存中;

qq_43985303的博客 3490

最新腾讯手游游戏appid列表及urlScheme一览 urlscheme查询

[全网独家] 2024最新腾讯游戏appid列表及urlScheme一览 手游包含王者荣耀QQ飞车我的世界PUBG吃鸡和平精英金铲铲之战三角洲行动QQ炫舞拳皇98OL欢乐斗地主 元梦之星使命召唤等

代码简单说 Vue、JAVA、PHP、Node.js 熟练运用,接口、架构、性能全搞定。 2万+

【Unity】【Photon】Photon Fusion2 的核心Unity组件 NetworkRunner 学习笔记

本文是学习Photon Fusion2 的核心Unity组件 NetworkRunner的学习笔记。

O青草O的博客 Unity和游戏制作知识分享 1271

Mybatis一级缓存和二级缓存

缓存可以将数据保存在内存中,是互联网系统常常用到的。目前流行的缓存服务器有 MongoDB、Redis、Ehcache 等。缓存是在计算机内存上保存的数据,读取时无需再从磁盘读入,因此具备快速读取和使用的特点。和大多数持久化框架一样,MyBatis 提供了一级缓存和二级缓存的支持。默认情况下,MyBatis 只开启一级缓存。mybatis的的一级缓存是SqlSession级别的缓存,一级缓存缓存的是对象,当SqlSession提交、关闭以及其他的更新数据库的操作发生后,一级缓存就会清空。

qq_53123736的博客 6897

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

MyBatis【四】一级缓存和二级缓存

文章目录MyBatis缓存1. 一级缓存2. 二级缓存 MyBatis缓存 一级缓存默认是开启的 二级缓存在映射配置文件中开启 Mybatis中的一级缓存和二级缓存: 【一级缓存】 它指的是Mybatis中SqlSession对象的缓存 当我们执行查询之后,查询的结果会同时存入到SqlSession为我们提供一块区域中。该区域的结构是一个Map。 当我们再次查询同样的数据,Myba...

iqqcode 9560

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

mybatis中一级缓存和二级缓存

1.一级缓存 一级缓存是SqlSession级别的缓存。在操作数据库时需要构造 sqlSession对象,在对象中有一个(内存区域)数据结构(HashMap)用于存储缓存数据。不同的sqlSession之间的缓存数据区域(HashMap)是互相不影响的。 Mybatis默认开启一级缓存。 一级缓存的作用域是同一个SqlSession,在同一个sqlSession中两次执行相同的sql语句,第一次执...

流的博客 2万+

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

Mybatis的一级缓存和二级缓存的理解和区别

一级缓存基于sqlSession默认开启,在操作数据库时需要构造SqlSession对象,在对象中有一个HashMap用于存储缓存数据。不同的SqlSession之间的缓存数据区域是互相不影响的。一级缓存的作用域是SqlSession范围的,当在同一个sqlSession中执行两次相同的sql语句时,第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次查询时会从缓存中获取数据,不再去底层数...

llziseweiqiu的博客 5万+

MyBatis一级缓存和二级缓存全面详解

一级缓存的内容不能跨sqlsession。由MyBatis自动维护。,缓存范围比一级缓存更大。不同的sqlsession可以访问二级缓存的内容。哪些数据放入二级缓存需要自己指定。

2401_87299389的博客 2941

mybatis一级缓存和二级缓存使用详解

针对mybatis一级缓存和二级缓存使用进行详细说明,搞清楚mybatis缓存的生命周期。

弹指天下 7019

Mybatis的一级缓存和二级缓存

验证mybatis缓存的存在,以及一级缓存如何保证数据一致性

hjkl761的博客 1万+

MyBatis的一级缓存和二级缓存

在首次访问时,查询数据库,将查询的数据库信息存入内存中;再次访问时可直接访问缓存,以减少IO、硬盘读写次数、提高效率。

Bbbcccccc的博客 2920

mybatis缓存详解,一级缓存和二级缓存举例讲解

mybatis缓存详解,一级缓存和二级缓存举例讲解

相关项目可以查看https://gitee.com/fan-pl或https://github.com/fpl1116 2279

mybatis 一级缓存和二级缓存简介

正如大多数持久层框架一样,MyBatis 同样提供了一级缓存和二级缓存的支持 一级缓存: 基于PerpetualCache 的 HashMap本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该Session中的所有 Cache 就将清空。   2. 二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMa

Skyline 1万+
上一篇: Mybatis的批量处理
下一篇: 高并发问题
Java_funds
博客等级 码龄9年 6粉丝 22原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值