范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

聊聊MyBatis缓存

  本文主要内容如下:
  一、MyBatis 缓存中的常用概念
  MyBatis 缓存:它用来优化 SQL 数据库查询的,但是可能会产生脏数据。
  SqlSession:代表和数据库的一次会话,向用户提供了操作数据库的方法。
  MappedStatement:代表要发往数据库执行的指令,可以理解为是 SQL 的抽象表示。
  Executor: 代表用来和数据库交互的执行器,接受 MappedStatment 作为参数。
  namespace:每个 Mapper 文件只能配置一个 namespace,用来做 Mapper 文件级别的缓存共享。
  映射接口:定义了一个接口,然后里面的接口方法对应要执行 SQL 的操作,具体要执行的 SQL 语句是写在映射文件中。
  映射文件:MyBatis 编写的 XML 文件,里面有一个或多个 SQL 语句,不同的语句用来映射不同的接口方法。通常来说,每一张单表都对应着一个映射文件。二、MyBatis 一级缓存2.1 一级缓存原理
  在一次 SqlSession 中(数据库会话),程序执行多次查询,且查询条件完全相同,多次查询之间程序没有其他增删改操作,则第二次及后面的查询可以从缓存中获取数据,避免走数据库。
  每个SqlSession中持有了Executor,每个Executor中有一个LocalCache。当用户发起查询时,MyBatis根据当前执行的语句生成MappedStatement,在Local Cache进行查询,如果缓存命中的话,直接返回结果给用户,如果缓存没有命中的话,查询数据库,结果写入Local Cache,最后返回结果给用户。
  Local Cache 其实是一个 hashmap 的结构:private Map cache = new HashMap(); 复制代码
  如下图所示,有两个 SqlSession,分别为 SqlSession1 和 SqlSession2,每个 SqlSession 中都有自己的缓存,缓存是 hashmap 结构,存放的键值对。
  键是 SQL 语句组成的 Key :Statement Id + Offset + Limmit + Sql + Params 复制代码
  值是 SQL 查询的结果:
  2.2 一级缓存配置
  在 mybatis-config.xml 文件配置,name=localCacheScope,value有两种值:SESSION 和 STATEMENT                     复制代码
  SESSION:开启一级缓存功能
  STATEMENT:缓存只对当前执行的这一个 SQL 语句有效,也就是没有用到一级缓存功能。
  首先我们通过几个考题来体验下 MyBatis 一级缓存。2.3 一级缓存考题
  考题(1)只开启了一级缓存,下面的代码调用了三次查询操作 getStudentById,请判断,下列说法正确的是?// 打开一个 SqlSession SqlSession sqlSession = factory.openSession(true); StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);  // 根据 id=1 查询学生信息 System.out.println(studentMapper.getStudentById(1));  // 根据 id=1 查询学生信息 System.out.println(studentMapper.getStudentById(1));  // 根据 id=1 查询学生信息 System.out.println(studentMapper.getStudentById(1)); 复制代码
  答案:第一次从数据库查询到的数据,第二次和第二次从 MyBatis 一级缓存查询的数据。
  解答:第一次从数据库查询后,后续查询走 MyBatis 一级缓存
  考题(2)只开启了一级缓存,下面代码示例中,开启了一个 SqlSession 会话,调用了一次查询,然后对数据进行了更改,又调用了一次查询,下列关于两次查询的说法,正确的是?// 打开一个 SqlSession SqlSession sqlSession = factory.openSession(true); StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);  // 根据 id=1 查询学生信息 System.out.println(studentMapper.getStudentById(1));  // 插入了一条学生数据,改变了数据库 System.out.println("增加了" + studentMapper.addStudent(buildStudent()) + "个学生");  // 根据 id=1 查询学生信息 System.out.println(studentMapper.getStudentById(1));  sqlSession.close(); 复制代码
  答案:第一次从数据库查询到的数据,第二次从数据库查询的数据
  解答:第一次从数据库查询后,后续更新(包括增删改)数据库中的数据后,这条 SQL 语句的缓存失效了,后续查询需要重新从数据库获取数据。
  考题(3)当开启了一级缓存,下面的代码中,开启了两个 SqlSession,第一个 SqlSession 查询了两次学生 A 的姓名,第二次 SqlSession 更新了一次学生 A 的姓名,请判断哪个选项符合最后的查询结果。SqlSession sqlSession1 = factory.openSession(true);  SqlSession sqlSession2 = factory.openSession(true);  StudentMapper studentMapper = sqlSession1.getMapper(StudentMapper.class);  StudentMapper studentMapper2 = sqlSession2.getMapper(StudentMapper.class); studentMapper2.updateStudentName("B",1);  System.out.println(studentMapper.getStudentById(1));  System.out.println(studentMapper2.getStudentById(1)); 复制代码
  答案:A B 复制代码
  解答:只开启一级缓存的情况下,SqlSession 级别是不共享的。代码示例中,分别创建了两个 SqlSession,在第一个 SqlSession 中查询学生 A 的姓名,第二个 SqlSession 中修改了学生 A 的姓名为 B,SqlSession2 更新了数据后,不会影响 SqlSession1,所以 SqlSession1 查到的数据还是 A。2.4 MyBatis 一级缓存失效的场景不同的SqlSession对应不同的一级缓存同一个SqlSession但是查询条件不同同一个SqlSession两次查询期间执行了任何一次增删改操作同一个SqlSession两次查询期间手动清空了缓存2.5 MyBatis 一级缓存总结MyBatis一级缓存内部设计简单,只是一个没有容量限定的 HashMap,在缓存的功能性上有所欠缺MyBatis的一级缓存最大范围是SqlSession内部,有多个SqlSession或者分布式的环境下,数据库写操作会引起脏数据,建议设定缓存级别为Statement一级缓存的配置中,默认是 SESSION 级别,即在一个MyBatis会话中执行的所有语句,都会共享这一个缓存。三、MyBatis 二级缓存3.1 MyBatis 二级缓存概述MyBatis的二级缓存相对于一级缓存来说,实现了SqlSession之间缓存数据的共享,同时粒度更加的细,能够到namespace级别,通过Cache接口实现类不同的组合,对Cache的可控性也更强。MyBatis在多表查询时,极大可能会出现脏数据,有设计上的缺陷,安全使用二级缓存的条件比较苛刻。在分布式环境下,由于默认的MyBatis Cache实现都是基于本地的,分布式环境下必然会出现读取到脏数据,需要使用集中式缓存将 MyBatis的Cache 接口实现,有一定的开发成本,直接使用Redis、Memcached 等分布式缓存可能成本更低,安全性也更高。3.2 MyBatis 二级缓存原理
  一级缓存最大的共享范围就是一个 SqlSession 内部,如果多个 SqlSession 之间需要共享缓存,则需要使用到二级缓存。
  开启二级缓存后,会使用 CachingExecutor 装饰 Executor,进入一级缓存的查询流程前,先在CachingExecutor 进行二级缓存的查询。
  二级缓存开启后,同一个 namespace下的所有操作语句,都影响着同一个Cache。
  每个 Mapper 文件只能配置一个 namespace,用来做 Mapper 文件级别的缓存共享。 复制代码
  二级缓存被同一个 namespace 下的多个 SqlSession 共享,是一个全局的变量。MyBatis 的二级缓存不适应用于映射文件中存在多表查询的情况。
  通常我们会为每个单表创建单独的映射文件,由于MyBatis的二级缓存是基于namespace的,多表查询语句所在的namspace无法感应到其他namespace中的语句对多表查询中涉及的表进行的修改,引发脏数据问题。3.3 MyBatis缓存查询的顺序
  先查询二级缓存,因为二级缓存中可能会有其他程序已经查出来的数据,可以拿来直接使用如果二级缓存没有命中,再查询一级缓存如果一级缓存也没有命中,则查询数据库SqlSession关闭之后,一级缓存中的数据会写入二级缓存。3.4 二级缓存配置
  开启二级缓存需要在 mybatis-config.xml 中配置: 复制代码3.5 二级缓存考题
  测试update操作是否会刷新该namespace下的二级缓存。
  开启了一级和二级缓存,通过三个SqlSession 查询和更新 学生张三的姓名,判断最后的输出结果是什么?SqlSession sqlSession1 = factory.openSession(true);  SqlSession sqlSession2 = factory.openSession(true);  SqlSession sqlSession3 = factory.openSession(true);  StudentMapper studentMapper = sqlSession1.getMapper(StudentMapper.class);  StudentMapper studentMapper2 = sqlSession2.getMapper(StudentMapper.class);  StudentMapper studentMapper3 = sqlSession3.getMapper(StudentMapper.class); System.out.println("studentMapper读取数据: " + studentMapper.getStudentById(1));  sqlSession1.commit();  System.out.println("studentMapper2读取数据: " + studentMapper2.getStudentById(1)); studentMapper3.updateStudentName("李四",1);  sqlSession3.commit();  System.out.println("studentMapper2读取数据: " + studentMapper2.getStudentById(1)); 复制代码
  答案:张三 张三 李四 复制代码
  解答:三个 SqlSession 是共享 MyBatis 缓存,SqlSession2 更新数据后,MyBatis 的 namespace 缓存(StudentMapper) 就失效了,SqlSession2 最后是从数据库查询到的数据。四、MyBatis 自定义缓存4.1 MyBatis 自定义缓存概述
  当 MyBatis 二级缓存不能满足要求时,可以使用自定义缓存替换。(较少使用)
  自定义缓存需要实现 MyBatis 规定的接口:org.apache.ibatis.cache.Cache。这个接口里面定义了 7 个方法,我们需要自己去实现对应的缓存逻辑。
  4.2 整合第三方缓存 EHCache
  EHCache 和 MyBatis 已经帮我们整合好了一个自定义缓存,我们可以直接拿来用,不需要自己去实现 MyBatis 的 org.apache.ibatis.cache.Cache 接口。
  添加 mybatis-ehcache 依赖包。 	org.mybatis.caches 	mybatis-ehcache 	1.2.1  复制代码
  创建EHCache的配置文件ehcache.xml。<?xml version="1.0" encoding="utf-8" ?>                       复制代码
  设置二级缓存的类型,在xxxMapper.xml文件中设置二级缓存类型 复制代码4.3 EHCache配置文件说明
  五、总结
  本篇分别介绍了 MyBatis 一级缓存、二级缓存、自定义缓存的原理和使用,其中还穿插了 4 道考题来验证 MyBatis 缓存的功能。不足之处是 MyBatis 缓存源码未分析。
  参考资料:
  tech.meituan.com/2018/01/19/…
  原文链接:https://juejin.cn/post/7156411054438744078

曝湾区翼龙憋大招!2700万抢郭艾伦打脸CBA,姚明不能承受这结果北京时间8月10日,郭艾伦的下家再度传来了关键变数,CBA名宿也是曾经在天津队效力的孟祥宇带来了爆料,郭少可能遭遇到湾区翼龙队400万美元的疯狂强挖。换算成人民币,这是2700万的UFC格斗之夜208赛后复盘全分析(主赛部分)北京时间7月24日繁星闪烁时分,UFC格斗之夜208暨UFCLondon伦敦站今年内第二度在英国首都的O2竞技场(O2Arena)举行。本期一共十四场比赛,共出现4场KOTKO获胜包贝尔和包文婧的爱恨情仇2015年,包贝尔顶替王宝强参加奔跑吧兄弟第二季,后又和杜鹃主演了徐峥执导的喜剧电影港囧。2016年,包贝尔和妻子包文婧在巴厘岛补办婚礼,因为伴娘事件引起轰动,后网传包贝尔封杀柳岩孙耀威谈被封杀经过冲动是魔鬼孙耀威,曾经的四小天王之一,最红时能跟刘德华郭富城比肩,人气更是一时无两。然而,就在他事业如日中天之时,他却亲手把自己的大好前程摔得粉碎,开启了人生的黑暗模式。年少轻狂2021年,林志颖惊喜现踪准备出院了?经纪人曝近况目前休养中记者林奕如台北报导林志颖7月22日驾驶特斯拉自撞分隔岛起火,被善心人士拖出车外救了一命,紧急送往林口长庚救治,全身多处受伤及骨折,经过手术治疗逐渐好转,目前转入普通病房,10日则是贾乃亮出事了!全网却开始心疼李小璐了贾乃亮因为一场商业直播,彻底翻车了!为什么网友的反应那么强烈?真正了解趣店老板前身和校园贷的人,都会对这场直播嗤之以鼻吧虽然贾乃亮第一时间撇清关系并公开道歉,但是大家依然不买账。其美澳间谍成蕾,藏身央视二十年,因口误暴露身份,结局大快人心说起央视主持人,很多观众都不谋而合地竖起大拇指,他们才华横溢,形象俱佳,能文能武,端庄稳重是央视女主持给大众的既定印象,并且时间身上始终萦绕着凌然正气。央视是我们国家对内和对外开放许晴坐头等舱吃泡面,镜头下尽显老态,网友真实了就在不久前,许晴一组穿着黄色薄纱裙,将头发全部盘起,坐在秋千上的写真大片刚刚惊艳了所有网友,令大家纷纷高呼少女感爆棚不愧是不老女神。近日,许晴坐头等舱吃泡面的生图就遭到了偶遇她的网巨兴茂结婚现场曝光!坐马车请秧歌队,杨志刚左手插兜被指不礼貌饿了吗?戳右边关注我们,每天给您送上最新出炉的娱乐硬核大餐!8月10日,多位网友在社交平台晒出演员巨兴茂结婚现场的视频,动态一出引起网友们的震惊。据悉,巨兴茂举办婚礼的地方正是在老发誓不回德云社的曹云金,风光过后,还是被打回了原形曹云金曾在节目中赌咒发誓,永生不回德云社。迄今为止,他确实做到了。但也为此付出了足够的代价。这边他的听云轩久无人问,惨遭倒闭。那边德云社蒸蒸日上,相声男团横空出道。曾经的曹云金多么窦骁的豪门情史,演山楂树之恋成名,情失程晓玥,牵手何超莲窦骁一何超莲在某寺庙敲钟祈福,小腹微微隆起(下图)今日头条公子误近日,何超莲晒出自己与窦骁出游的vlog,视频中何超莲与窦骁,一起在某寺庙祈福敲钟。何超莲不经意间露出了自己微微隆起
买手机别小家子气,2022年值得入手的4款手机,用到2027年不卡顿不要总是盯着百元机和入门千元机,虽说那些手机价格便宜,看上去很有诱惑力,但手机毕竟是贴身物品,我们每天都要使用,多花一些钱买一款好手机,自己日常用着也开心,而且相比入门机型会更加耐腾讯京东阿里巴巴,大厂裁员潮来了!职场中最安全的人有哪些特征2022年是疫情持续蔓延的第三年,传统行业实体经济下滑的同时,互联网行业也停止了往年持续扩张的一片向好的繁荣景象。终于在2223财年到来的时候,来了最凶猛的一波裁员潮。没有N1,没正式出山!CBA名将加盟浙江男篮,能否帮助球队打进四强?浙江男篮休赛期进行了换帅工作,刘维伟下课之后,他的助理教练王世龙成功上位。除了王世龙之外,据了解,CBA名将丁锦辉也是出山执教,新赛季将会加盟浙江男篮教练组,担任球队助理教练,能否恭喜!TVB知名男星与富婆未婚妻正式结婚,网友可以少奋斗10年本文编辑剧透社issac未经授权严禁转载,发现抄袭者将进行全网投诉恭喜,恭喜!据港媒最新报道,香港男演员TVB知名男星伍富桥(Alvin)正式升级成为豪门女婿。他在富婆未婚妻梁兆盈陈乔恩艾伦婚后自驾出游,自己用全妆滤镜,给老公拍照却全程素颜引子新金牌娱乐观察家发现,陈乔恩老师自从和艾伦结婚以后,状态非常好。最近,陈乔恩和艾伦婚后自驾出游,女神给自己用了全妆滤镜,不过给老公艾伦拍照却明显是素颜。你们怎么看?第一个问题陈昔日何榜成笑话,八面玲珑也抵不住人走茶凉,何炅衰落太现实人走茶凉是一种什么感觉?这不免让人想起了何炅之前与现在的处境。曾有近乎半个娱乐圈人士,贡献了两组堪称盛世的生日祝福排行榜。他们凌晨时分,通过社交平台准时送上生日祝福。其中包含一线明于谦的人生智慧文文刀贰1984年,在北京曲艺团的后台发生了一件大事。相声部专业老师王世臣与团领导围坐在一起,不为别的,只为了决定一个13岁孩子的去与留。劝退在当时并不多见,但却被王世臣赶上了。可关牧村事业和情感坎坷有泪,69岁的她给百岁老父尽孝点击关注,每天都有名人故事感动您!关牧村关牧村是德艺双馨的著名女中音歌唱家,上世纪八九十年代红极一时,被媒体誉为国内女中音第一人。她演唱的打起手鼓唱起歌吐鲁番的葡萄熟了金风吹来的时周迅离婚后依然红,还收获姐弟恋,前夫高圣远的现状怎样?点击关注,每天都有名人故事感动您!周迅周迅是公认的演技派女星,主演了龙门飞甲红高粱风声画皮夜宴李米的猜想如懿传大明宫词恋爱中的宝贝像雾像雨又像风等一系列经典影视作品。作为获奖专业户结婚24年分居12年?私底下的陈小艺,是一个怎样的人2005年3月份,孙红雷在电视剧半路夫妻拍摄现场,央求边上的导演说要不你回避一下吧。当时正在拍摄的,是一段接吻戏。男主角孙红雷,女主角陈小艺,而导演,正是陈小艺的丈夫刘惠宁。孙红雷入戏太深以贾宝玉自诩,苦追陈晓旭遭拒,32岁酗酒暴病永远离开马广儒在87版红楼梦中饰演贾瑞的剧照说起马广儒,大多数人都是一脸懵。但提起87版红楼梦,全中国只怕无人不知无人不晓。红楼梦是流传千古的文学巨制,而87版红楼梦则是将这部鸿篇巨制以最