缓存在哪里_什么是MyBatis缓存技术

MyBatis缓存

引言

在一个Web项目中,查询数据库中的操作算是一个非常常用的操作,但是有些数据会被经常性的查询,而每一次都去数据库中查询这些重复的数据,会很消耗数据库的资源,同时使得查询效率也很低,而 MyBatis 中就通过缓存技术来解决这样的问题,也就是说:将一些经常查询,并且不经常改变的,以及数据的正确对最后的结果影响不大的数据,放置在一个缓存容器中,当用户再次查询这些数据的时候,就不必再去数据库中查询,直接在缓存中提取就可以了

注:缓存可以简单理解为存在于内存中的临时数据

MyBatis 提供了 一级缓存和二级缓存两种形式

  • 一级缓存 :它是 SqlSession 级别的缓存,SqlSession 类的实例对象中提供了一个 HashMap 的结构,可以用于存储缓存数据,当我们再次查询同一数据的时候,MyBatis 会先去 SqlSession 中查询,有的话,就直接调用
  • 二级缓存 :是Mapper 级别的缓存,也就是说,如果多个 SqlSession 类的实例,去操作同一个Mapper配置文件中的SQL,这些实例对象可以共用二级缓存
7f527cdcba8d450cd5594a9b80389507.png

一级缓存

(1) 基本阐述

上面我们总的讲了一级缓存的原理,现在梳理一下它细节

以一个通过 id 查询用户的例子来说

  • 第一次查询 id 为某个值的用户信息时,先去 SqlSesion 的一级缓存中去寻找,如果找到了,就直接用,如果没有找到就去数据库中去查,然后将查到的内容存到一级缓存区域
  • 但是,如果在下一次操作中,执行了 commit 操作,也就是执行了增删改的操作,一级缓存区域内的内容会被清空,这是为了保证缓存中的数据的有效性,避免脏读的产生
d63fa1ae5060f0e7a8b8752277a4e5a9.png

(2) 程序演示

演示前,我把需要准备的一些类或者表现贴出来

User表

CREATE TABLE USER ( `id`            INT(11)NOT NULL AUTO_INCREMENT, `username`     VARCHAR(32) NOT NULL COMMENT '用户名', `telephone`    VARCHAR(11) NOT NULL COMMENT '手机', `birthday`        DATETIME DEFAULT NULL COMMENT '生日', `gender`          CHAR(1) DEFAULT NULL COMMENT '性别', `address`         VARCHAR(256) DEFAULT NULL COMMENT '地址',  PRIMARY KEY  (`id`)) ENGINE=INNODB DEFAULT CHARSET=utf8;

User实体类

public class User implements Serializable {    private Integer id;    private String username;    private String telephone;    private Date birthday;    private String gender;    private String address;    ...... 请补充 get set 方法}

UserMapper接口

public interface UserMapper {    /**     * 根据id查询用户信息     * @param userId     * @return     */    User findById(Integer userId);}

UserMapper.xml

<?xml version="1.0" encoding="UTF-8"?>       SELECT * FROM user where id = #{uid}    

测试方法

/*** 测试查询所有*/@Testpublic void testFirstLevelCache() {    User user1 = userMapper.findById(16);    System.out.println(user1);    User user2 = userMapper.findById(16);    System.out.println(user2);    System.out.println(user1 == user2);}

执行效果

0582e3fcdecb4bca7c8aded45771612b.png
e088bea1b51d7c67142082d17607d4b5.png

可以很明显的看到,当我们在同一个 sqlSession的情况下,当我们第一次查询 id 值为 16 的用户时,从数据库中确实查询到了数据,而第二次查询的时候,却没有任何日志的数据,而同时我们可以看到,通过输出语句,看到两个对象是完全相同的,这也就意味着,第二次查询不是从数据库查询出来的,而是从缓存中

二级缓存

(1) 基本阐述

通过上面的简单认识,我们认识到一级缓存是基于同一个 SqlSession的,但是有时候由于方法封装的原因,或者在查询完,SqlSession 对象会关闭,一级缓存就清空了,会导致无法从中获取内容

二级缓存的可以帮我们解决一级缓存无法使用的情况,前面已经说过二级缓存是Mapper 级别的缓存,多个SqlSession类的实例对象加载同一个Mapper配置文件,并执行其中SQL配置的收,他们就共享同一个 Mapper 缓存,执行流程也与一级缓存基本是一致的

  • 查询时,先去Mapper缓存区去找这个值,如果找不到,就去数据库查,然后将查询到的结果存储到缓存中,等下次使用
  • 当某个 SqlSession 类的实例对象执行了增删改操作时,二级缓存会被清空
520ad2bad92cef3a765442d0b4062eb3.png

还依据刚开始准备的代码,我们直接写出其测试代码,看看在不同的 SqlSession 下,加载同一个Mapper的SQL是否会看到二级缓存的效果

(2) 程序演示

测试代码

@Testpublic void testSecondLevelCache() {    SqlSession sqlSession1 = factory.openSession();    UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);    User user1 = mapper1.findById(16);    sqlSession1.close();    SqlSession sqlSession2 = factory.openSession();    UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);    User user2 = mapper2.findById(16);    sqlSession1.close();    System.out.println(user1 == user2);}

第一次执行效果

c88c74279fcd518b6de1516e763e5220.png

看完测试代码,我们发现,SQL执行了两次,很显然,没有达到了我们的期望,那么是哪里不对呢?

答案是,在MyBatis中一级缓存是默认开启的,而二级缓存则需要进行配置开启

要开启二级缓存,需要进行两个操作步骤

  • ①:在总配置文件 SqlMapConfig.xml 中配置 setting属性
  • ②:在SQL映射文件中开启二级缓存
47731ea58726d32aacde45aa0ec4fa57.png

通过官网的文档,可以看到,默认值就是true,所以,不配置也是可以的,不过我们还是先给出来

修改 SqlMapConfig.xml

修改 UserMapper.xml

只需要在文件中添加一个 cache标签就可以了,非常简单

执行效果

2d726aa4733418f2c8c9f83fedee93dd.png

还有一个需要注意的地方,那就是我们最后做的判断 System.out.println(user1 == user2); 为什么的到的结果却是 false呢?

这是因为,在二级缓存中,存入的是值,而不是对象,当需要使用的时候,会创建出新的用户,然后将值传入,所以这里是不等的

不过使用二级缓存的时候,一定要谨慎,因为有时候不同的namespace下的 SQL配置中可能缓存着相同的数据,如我们上面的例子,UserMapper.xml 中有关于 user表的操作,但是如果在其他 Mmpper.xml 中仍然有针对 user 单表的操作,这会导致两方数据不一样,如果在我们 UserMapper.xml 进行了刷新缓存,但是另一个Mapper.xml 中可能仍有效,所以可能会出现错误

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/296520.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

无法打开物理文件 操作系统错误 5:拒绝访问 SQL Sever

今天分离附加数据库&#xff0c;分离出去然后再附加&#xff0c;没有问题。但是一把.mdf文件拷到其它文件夹下就出错&#xff0c;错误如下&#xff1a; 无法打开物理文件 "E:\db\homework.mdf"。操作系统错误 5:"5(拒绝访问。)"。 (Microsoft SQL Server&…

WPF开发登录窗口之——窗口布局

WPF开发者QQ群&#xff1a; 340500857 | 微信群 -> 进入公众号主页 加入组织01—代码如下一、创建项目&#xff0c;命名为LoginWindow&#xff0c;然后创建以下目录结构&#xff1a;二、导入图片三、创建资源字典。一共创建四个&#xff1a;ButtonStyle、WindowStyle、Text…

这个偏僻的小山村竟出了12位博士28位硕士,高产“学霸”背后原因曝光......

全世界只有3.14 % 的人关注了爆炸吧知识考上大学留名祖宗祠堂今早&#xff0c;超模君刷微博的时候&#xff0c;有一则新闻吓得我虎躯一震——一个总共才2000多人小山村&#xff0c;竟然出了12位博士28位硕士。而且考上大学的孩子&#xff0c;他们的名字直接刻进祖宗祠堂。(微博…

Android应用程序消息处理机制(Looper、Handler)分析(5)

ActivityThread类的这个mH成员变量是什么时候创建的呢&#xff1f;我们前面在分析应用程序的消息循环时&#xff0c;说到当应用程序进程启动之后&#xff0c;就会加载ActivityThread类的main函数里面&#xff0c;在这个main函数里面&#xff0c;在通过Looper类进入消息循环之前…

现在银行etl还要做拉链表吗_hive 拉链表 实现全量数据 增量更新

背景&#xff1a;数据表字段有IP&#xff0c;IP省份&#xff0c;IP城市&#xff0c;最新访问时间&#xff0c;假如目前一共有100W的IP我第一次初始化的时候完成初始化表插入&#xff0c;然后每天都有5W左右的IP活跃&#xff0c;然后我要更新这5W个IP的记录到初始化的表&#xf…

牛顿新定律:凭本事得到的,凭什么要还?

后记事后&#xff0c;超模君提出用上帝开过光的真苹果来换回自己的苹果手机&#xff0c;但是惨遭牛顿君拒绝&#xff0c;理由是苹果手机更能激发他的创作灵感……面对这种鬼话&#xff0c;超模君敢怒不敢言。更惨的是&#xff0c;上帝说苹果手机不报销……艾萨克牛顿&#xff0…

NOI导刊模拟2—电话网络 解题报告

题目大意&#xff1a;给出一个图&#xff0c;顶点为1到n和一个值k&#xff0c;求出包含顶点1到顶点n的通路的子图中&#xff0c;第k1大的边最短为多少&#xff1f;&#xff08;若存在一条从1到n路径边数小于等于k&#xff0c;则返回0&#xff0c;若不存在通路&#xff0c;返回-…

好书推荐 -《国富论》-15-09

好书推荐-《国富论》-15-09.md—/Users/zjh/Documents书籍 《国富论》-亚当斯密-陕西师范大学出版社 推荐理由 《国》是一本非常通俗易懂的经济书籍&#xff0c;用简单的语言讲解从个体&#xff0c;到小型市场&#xff0c;再到国家和政府的经济结构和规律。虽然亚当斯密的一些观…

04Prism WPF 入门实战 - Module

1.概要源码及PPT地址&#xff1a;https://github.com/JusterZhu/wemail视频地址&#xff1a;https://www.bilibili.com/video/BV1KQ4y1C7tg?sharesourcecopywebModule&#xff0c;具有特定功能&#xff0c;且独立存在则称为成为模块。下图为Prism体系中的关系结构图。在Prism体…

虚拟机(VMware Workstation)中,把连接网络的模式由“NAT模式”,改成“自动桥接模式”,网速大大的提升...

安装虚拟机&#xff0c;默认情况下&#xff0c;联网的模式是NAT&#xff0c;即跟主机是转发共用网络资源的&#xff0c;这样就非常慢&#xff0c;时常网页都打不开&#xff0c;现把它改成桥接模式&#xff0c;让它独立成为一台物理机&#xff0c;网速有大大的改善&#xff0c;设…

如何保持纯洁男女关系……

1 倒也没毛病▼2 差点以为是狗子&#xff01;&#xff01;▼3 大哥&#xff1a;我裤子没破&#xff01;▼4 女朋友梦到了啥&#xff1f;&#xff1f;▼5 忍不住了&#xff0c;嘻嘻嘻...&#xff08;via.小风车车&#xff09;▼6 亲爸爸&#xff01;&#xff01;▼7 哈哈哈…

【转】一个关于fork()的笔试题,考了好几遍,终于找到答案了

笔试至少3次见到这个题&#xff0c;都是瞎编的&#xff0c;今天群里有人问&#xff0c;然后有人放出了这个地址&#xff1a;http://coolshell.cn/articles/7965.html&#xff0c;让我恍然大明白&#xff0c;豁然好脾气。 感谢这位陈皓同学&#xff08;名字很熟&#xff0c;不记…

android自定义金额输入键盘_Android 自定义输入支付密码的软键盘实例代码

Android 自定义输入支付密码的软键盘有项目需求需要做一个密码锁功能&#xff0c;还有自己的软键盘&#xff0c;类似与支付宝那种&#xff0c;这里是整理的资料&#xff0c;大家可以看下&#xff0c;如有错误&#xff0c;欢迎留言指正需求&#xff1a;要实现类似支付宝的输入支…

IE6 IE8下背景图片不显示问题

更改background:url()no-repeat; 去掉no-repeat即可解决问题&#xff01;转载于:https://www.cnblogs.com/dream-w/p/4781644.html

C# 选中 DataGridView 控件中的行时显示不同的颜色

可以利用 DataGridView 控件的 SelectionMode、ReadOnly 和 SelectionBackColor 属性实现当选中DataGridView控件中的行时显示不同的颜色。SelectionMode属性用于设置如何选择 DataGridView 的单元格。语法如下:public DataGridViewSelectionMode SelectionMode{get;set;}属性值…

Objective-C( Foundation框架 一 常见的结构体)

常见的结构体 &#xff08;NSPoint&#xff0c;CGPoint&#xff09;、&#xff08;NSRange&#xff0c;CGRange&#xff09;、&#xff08;NSSize&#xff0c;CGSize&#xff09; 苹果官方推荐使用CG开头的结构体 NSRange是Foundation框架中常见的结构体它的定义如下&#xff1…

32岁武汉硕士毕业4年后重新高考,考上本硕需再读8年:“不是一时冲动”

全世界只有3.14 % 的人关注了爆炸吧知识9月5日&#xff0c;程传坤收到了湖北中医药大学的录取通知书。7月8日下午5时10分&#xff0c;32岁的程传坤走出湖北省武汉市新洲一中考点&#xff0c;一脸轻松&#xff0c;拿着准考证特意在新洲一中门前留影。这是他硕士毕业4年后再战高考…

打开本地文件_可以跨软件搜索文件?结构式检索你一定要学会!

面对电脑中日积月累的大量结构式&#xff0c;如何能快速找到自己想要的文件&#xff0c;有时真是一个让人头疼的问题。KingDraw PC版内置的结构式检索功能&#xff0c;可以帮助我们轻松解决这个难题。KingDraw PC版中&#xff0c;我们有两种途径可以检索结构式——右键菜单中检…

C# static readonly 与 const 的区别

static readonly 与 const 的区别&#xff1a; const 表达式的值是在编译时形成的&#xff1b; static readonly 表达式的值直到程序运行时才形成&#xff1b;转载于:https://www.cnblogs.com/xiangfeideshui/archive/2012/10/15/2724260.html

WPF实现雷达图(仿英雄联盟)

WPF开发者QQ群&#xff1a; 340500857 | 微信群 -> 进入公众号主页 加入组织转载 有小伙伴提出需要实现雷达图。 由于在WPF中没有现成的雷达图控件&#xff0c;所以我们自己实现一个。PS&#xff1a;有更好的方式欢迎推荐。01—代码如…