首页 / 知识
Mybatis 中的一级缓存与二级缓存
2023-04-11 16:28:00

一,Mybatis中为什么要有缓存
缓存的意义是将用户经常查询的数据放入缓存(内存)中去,用户去查询数据的时候就不需要从磁盘(关系型数据库)中查询,直接从缓存中查询,从而提高了查询效率,解决了高并发中系统的性能问题。Mybatis中提供一级缓存与二级缓存。
Mybatis的一级缓存是一个SqlSession级别的缓存,只能访问自己的一级缓存数据,而二级缓存是Mapper级别的缓存,是跨SqlSession的,不同的SqlSession是可以共享缓存数据的。
二,一级缓存
Mybatis 一级缓存原理:
第一次发出查询请求,sql 查询的结果写入SqlSession的一级缓存当中,缓存使用的数据结构是一个map<key, value>
key : hashcode + sql + sql输入参数 + 输出参数 (sql的唯一标识)
value : 用户信息
同一个SqlSession再次发出相同的sql,就会从缓存中读取而不走数据库,如果两次操作之间出现commit(修改、输出、添加)操作,那么本SqlSession中一级缓存区域全部清空,下次再去缓存中查不到所以要从数据库中查询,从数据库再写入一级缓存。
@Test
public void createTable(){
SqlSession sqlSession = DBUtil.getSqlSession();
List<Map<String, Object>> list1 = sqlSession.selectList("com.snow.xml.SnowOracle.getEmployeeByName", "周康");
System.out.println(list);
List<Map<String, Object>> list2 = sqlSession.selectList("com.snow.xml.SnowOracle.getEmployeeByName", "周康");
System.out.println(list2);
}
在数据库中有一张Employee表,里面有一条数据,通过selectList的方法查询,结果如下[{ID=70DD7D10-9FC6-4B79-ADAF-8B408DE1E048, EMPNAME=周康, AGE=36, DMGRP=男, BIRTHDATE=1987-07-31 00:00:00.0, SALARY=17000, ADDRESS=湖南长沙, GRADE=高级架构师}]
此时,手动修改数据库该人的年龄,手动修改为35,然后保存
此时,在运行代码,查看list2的值,两次结果一致,都是36 并非 35,说明第二次相同的查询走的是SqlSession中的一级缓存。
Mybatis 中一级缓存需要注意的点 :
Mybatis 中一级缓存是默认开启的,不需要手动配置。
Mybatis 和 Spring 整合后进行 mapper 代理开发后,不支持一级缓存。Mybatis 和 Spring 整合,Spring 按照 mapper 的模板去生成 mapper 代理对象,模板中在最后会统一关闭 SqlSession。
三、二级缓存
Mybatis二级缓存原理:
二级缓存的范围是mapper级别(mapper同一个命名空间),mapper以命名空间为单位创建缓存数据结构,结构是map<key, value>。每次查询前看是否开启了二级缓存,如果开启则从二级缓存的数据结构中取缓存数据,如果二级缓存中没有取到,再从一级缓存中取,如果一级缓存也没有,那就从数据库中查询。
二级缓存配置
需要在Mybatis的配置文件中<settings>标签中配置二级缓存:
<settings>
<setting name="cacheEnabled" value="true"/> <!--Mybatis的二级缓存配置-->
</settings>
Mybatis的二级缓存的范围是mapper级别的,因此我们mapper如果想要使用二级缓存,还需要在对应的映射文件中配置<cache>标签
<mapper namespace="com.snow.xml.SnowOracle">
<cache></cache> <!--Mybatis的二级缓存配置-->
</mapper>
测试:
@Test
public void test(){
SqlSession sqlSession1 = DBUtil.getSqlSession();
List<Map<String, Object>> list1 = sqlSession1.selectList("getEmployeeByName", "周康");
System.out.println("list1=" + list1);
sqlSession1.commit();
sqlSession1.close();
DBUtil.closeSqlsession();
SqlSession sqlSession2 = DBUtil.getSqlSession();
List<Map<String, Object>> list2 = sqlSession2.selectList("getEmployeeByName", "周康");
System.out.println("list2=" + list2);
sqlSession2.commit();
sqlSession2.close();
}
在SqlSession2 创建处打断点,观看此时输出:list1=[{ID=70DD7D10-9FC6-4B79-ADAF-8B408DE1E048, EMPNAME=周康, AGE=35, DMGRP=男, BIRTHDATE=1987-07-31 00:00:00.0, SALARY=17000, ADDRESS=湖南长沙, GRADE=高级架构师}]
此时去修改数据库中周康此人的年龄,改为37提交,代码继续往下执行,会看到SqlSession2 与SqlSession1 是两个不同的SqlSession,观看此时输出:list2=[{ID=70DD7D10-9FC6-4B79-ADAF-8B408DE1E048, EMPNAME=周康, AGE=35, DMGRP=男, BIRTHDATE=1987-07-31 00:00:00.0, SALARY=17000, ADDRESS=湖南长沙, GRADE=高级架构师}]
|
最新内容
相关内容
For循环如何在Python中工作
For循环如何在Python中工作,工作,项目,代码,培训,流程,示例,序列,语句,语法,实际,Python的for循环通过遍历数组的序列来工作。从本质上讲,它在编写一个简单的游戏来学习 Python
编写一个简单的游戏来学习 Python,数字,标准,概念,名称,异常,软件,基础知识,培训,通用,流程,通过编写一个“猜数字”游戏来探索Python(和其他如何杀死一个Python线程
如何杀死一个Python线程,状态,线程,代码,标准,意外,工作,控制权,培训,事件,结束,我经常被问到如何杀死一个后台线程,这个问题的答案让很多人不Python中的Mock
Python中的Mock,项目,产品,工作,方法,系统,标准,数据,业务,地址,服务,1.前言微服务架构下,由于各类服务开发进度的不一致,导致联调工作经常会存为何你的Python代码应是扁平与稀疏
为何你的Python代码应是扁平与稀疏的,代码,培训,信息,观察,设计,工具,嵌套,闻闻,程序员,沉思,Python之禅之所以得名,正是由于它那简明扼要的规用Python开发一个简单的猜数字游戏
用Python开发一个简单的猜数字游戏,数字,代码,培训,官网,设备,程序,玩家,注释,内容,游戏,本文介绍如何使用Python制作一个简单的猜数字游戏。Python与c#的区别
Python与c#的区别,代码,平台,名称,培训,系统,设计,技术,标准,脚本,变量,现在来看下c#。它们的技术差异很大,但都适用于web开发。Python对c#的数据科学中必须了解的Python核心库
数据科学中必须了解的Python核心库,数据,生产,代码,标准,分析,培训,图片,工具,统一,涉足,python有三个核心数据科学库,在此基础上还创建了许多Python 里面的一些小技巧
Python 里面的一些小技巧,分析,代码,培训,字典,条件,表示,表达式,下面,里面,列表,三元条件判断的3种实现方法C语言中有三元条件表达式,如a>b?aPython 中如何实现参数化测试?
Python 中如何实现参数化测试?,密码,数据,测试,业务,情况,预期,培训,系统,参数,方法,之前,我曾转过一个单元测试框架系列的文章,里面介绍了unitPython中heapq与优先队列
Python中heapq与优先队列,代码,电脑,名字,情况,函数,队列,标准,价格,基础,培训,今天的文章来介绍Python当中一个蛮有用的库——heapq。heapqPython 中的装饰器是什么
Python 中的装饰器是什么,包装,函数,代码,基础,工具,培训,变量,对象,参数,语法,装饰器在Python中是一个非常强大和有用的工具,因为它允许程序