mybatis缓存机制(转)
缓存在互联网系统中是非常重要的, 其主要作用是将数据保存到内存中, 当用户查询数据 时, 优先从缓存容器中获取数据,而不是频繁地从数据库中查询数据,从而提高查询性能。目 前流行的缓存服务器有MongoDB 、Redis 、Ehcache 等,不同的缓存服务器有不同的应用场景, 不存在孰优孰劣。 MyBatis 提供一级缓存和二级缓存的机制。一级缓存是SqlSession 级别的缓存, 在操作数据 库时, 每个SqlSession 类的实体对象中都有一个HashMap 数据结构可以用来缓存数据,不同的 SqlSession 类的实例对象缓存的HashMap 数据结构互不影响。二级缓存是Mapper 级别的缓存, 多个SqlSession 类的实例对象操作同一个Mapper 配置文件中的SQL 语句,可以共用二级缓存, 二级缓存是跨SqlSession 的。这里需要注意的是,在没有配置的默认情况下, MyBatis 只开启一 级缓存。
My Batis 的缓存模式如图所示:
一级缓存
概述
MyBatis 的一级缓存是SqI Session 级别的缓存, 在操作数据库时需要构造Sq!Session 对象。 每个SqISession 对象中都有一个HashMap 对象用于缓存数据,不同的SqlSession 之间的缓存数 据区域互不影响。 MyBatis的一级缓存作用域是SqlSession 范围的,在参数和SQL 完全一样的情况下,使用 同一个SqlSession 对象调用同一个Mapper 方法,往往只执行一次SQL ,因为MyBatis 会将数据 放在缓存中,下次查询的时候,如果没有声明需要刷新缓存并且缓存没有超时, SqlSession 都 只会取出当前缓存的数据,而不会再次发送SQL 到数据库中。需要注意的是,如果SqlSession 执行了DML 操作( insert 、update 和delete ),并提交到数据库, MyBatis 会清空SqlSession 中 的一级缓存,这样做的目的是为了保证缓存中存储的是最新的信息, 以避免出现脏读现象。 MyBatis 的缓存机制是基于id 进行缓存的, MyBatis 使用HashMap 缓存数据时,使用对象的id 作为key,而对象则作为value 保存。
示例
上述代码中,通过@Resource 注解注入SqlSessionFactoryBean 对象, SqlSessionFactoryBean 对象在applicationContext.xml 配置文件中己配置, 具体代码如下:
通过SqlSessionFactory 工厂获取SqlSession 对象, 通过SqlSession 对象的getMapper()方法 获取AyUserDao 接口对象, 并执行AyUserDao 接口对象的findByld()方法。AyUserDao 和 AyUserMapper.xml 的代码如下所示。
执行测试用例testsessionCach e(),控制台打印相关的信息,具体如图9-2 所示。
由图9 -2 中控制台打印的信息可以看出,第一次查询和第二次查询,查询SQL 的日志只输 出一遍, 这就说明了第二次查询的数据不是从数据库查询出来的,是从一级缓存中获取的。
生命周期
MyBatis 在开启一个Session 会话时, 会创建一个新的SqISession 对象, 每个SqlSession 对 象会创建一个新的Executor 对象, Executor 对象中持有一个新的PerpetualCache 对象: 当会话结 束时, SqISession 对象及其内部的Executor 对象还有PerpetualCache 对象也会一并释放掉,即: (1 )如果SqlSession 调用了close()方法,会释放掉一级缓存PerpetualCache 对象, 一级缓 存不可用。 (2 )如果SqlSession 调用了clearCache(), 会清空PerpetualCache 对象中的数据,但是该对 象仍可使用。 ( 3 ) SqlSession 中执行任何一个DDL 操作( update 、delete 、insert) ,都会清空 PerpetualCache 对象的数据,但是该对象可以继续使用。
二级缓存
概述
二级缓存是Mapper 级别的缓存。使用二级缓存时,多个SqlSession 使用同一个Mapper ( namespace )的SQL 语句操作数据库,得到的数据会存在二级缓存区域,二级缓存同样是使用 HashMap 进行数据存储。二级缓存比一级缓存作用域范围更大,多个SqISession 可以共用二级 缓存,二级缓存是跨SqISession 的。当某个SqISession 类的实例对象执行了增、删、改等操作 时, Mapper 实例会清空二级缓存。MyBatis 默认没有开启二级缓存,需要在配置中开启二级缓 存。开启二级缓存的步骤如下。
首先,在applicationContext.xml 配置文件中添加如下配置:
上面配置信息中最重要的就是指定MyBatis 配置文件的位置:
其次,在src\main\resources 目录下添加配置文件mybatis-config . xml , 具体代码如下:
最后,由于二级缓存是Mapper 级别的,还要在需要开启二级缓存的具体mapper.xml 文件 中开启二级缓存,方法很简单,只需要在mappe川ml 文件中添加一个cache 标签既可,具体代 码如下所示:
cache 标签有很多属性,常用的属性如表9- 1 所示:
示例
AyUserDao 和AyUserMapper.xml 代码如下:
当开启MyBatis 二级缓存后,执行测试用例testSessionCache(), 控制台打印相关的信息, 具体如图9-4 所示。
由图9-4 可知, 第一次查询数据时, 获取连接、编译SQL、加载了数据库中的数据。而第 二次查询数据之前,进行了update 操作,相当于进行commit 操作,也就是说会清空一级缓存来 保证数据的最新状态。但是开启了二级缓存,在第二次查询时,会从二级缓存中获取数据。 这里需要注意的是,如果在select 标签中设置“ userCache = false” 可以禁用当前select 语句 的二级缓存,具体代码如下:
这里简单总结一下二级缓存的特点:
还需要注意的是,使用二级缓存需要特别谨慎,有时候不同的namespace 下的SQL 配置可 能缓存了相同的数据。例如AyUserMapper.xml 中有很多查询缓存了用户数据,其他的 XXXMapper且nl 中有针对用户表进行单表操作, 也缓存了用户数据,如果在AyUserMapper.xml 中做了刷新缓存的操作,在XXXMapper.xml 中的缓存数据仍然有效, 这样在查询数据时可能会 出现脏数据。所以使用MyBatis 的二级缓存时,要根据具体的业务情况,谨慎使用。
###cache-ref共享缓存
MyBatis 并不是整个Application 只有一个Cache 缓存对象,它将缓存划分的更细, 也就是 Mapper 级别的,即每一个Mapper 都可以拥有一个Cache 对象,具体如下:
( 1 ) 为每一个Mapper 分配一个Cache 缓存对象(使用<cache>节点配置) 。 ( 2 )多个Mapper 共用一个Cache 缓存对象(使用<cache-ref>节点配置) 。
如果想让多个Mapper 共用一个Cache ,可以使用<cache-ref namespace="与节点,来指定这 个Mapper 共享哪一个Mapper 的Cache 缓存。具体如图9-5 所示。
mybatis缓存原理
工作原理
如图9- 6 所示, 一个SqlSession 对象中创建一个本地缓存( local cache ),对于每次查询, 都会根据查询条件去一级缓存中查找,如果缓存中存在数据,就直接从缓存中取出,然后返回 给用户:否则,从数据库读取数据,将查询结果存入缓存并返回给用户。
SqlSession 将它的工作交给了Executor 执行器这个角色来完成,负责完成对数据库的各种 操作。当创建一个SqlSession 对象时, MyBatis 会为这个SqlSession 对象创建一个新的Executor 执行器,而缓存信息就被维护在这个Executor 执行器中, MyBatis 将缓存和对缓存相关的操作 封装成了Cache 接口。
如图9 - 7 所示, MyBatis 的二级缓存机制的关键是使用Executor 对象。当开启SqlSession 会 话时, 一个Session 对象使用一个Executor 对象来完成会话操作。如果用户配置了 "cacheEnabled=true”, 那么MyBatis 在为SqlSession 对象创建Executor 对象时,会对Executor 对 象加上一个装饰者: CachingExecutor ,这时SqISession 使用CachingExecutor 对象来完成操作请 求。CachingExecutor 对于查询请求,会先判断该查询请求在二级缓存中是否有缓存结果,如果 有查询结果, 则直接返回缓存结果:如果缓存中没有, 再交给真正的Executor 对象来完成查询 操作,之后CachingExecutor 会将真正Executor 返回的查询结果放置到缓存中,然后再返回给 用户。
mybatis缓存机制(转)的更多相关文章
- mybatis缓存机制
目录 mybatis缓存机制 Executor和缓存 一级缓存 小结 二级缓存 小结 mybatis缓存机制 mybatis支持一.二级缓存来提高查询效率,能够正确的使用缓存的前提是熟悉mybatis ...
- 聊聊MyBatis缓存机制【美团-推荐】
聊聊MyBatis缓存机制 2018年01月19日 作者: 凯伦 文章链接 18778字 38分钟阅读 前言 MyBatis是常见的Java数据库访问层框架.在日常工作中,开发人员多数情况下是使用My ...
- 《深入理解mybatis原理4》 MyBatis缓存机制的设计与实现
<深入理解mybatis原理> MyBatis缓存机制的设计与实现 本文主要讲解MyBatis非常棒的缓存机制的设计原理,给读者们介绍一下MyBatis的缓存机制的轮廓,然后会分别针对缓存 ...
- Mybatis缓存机制及mybatis的各个组成部分
Mybatis 一级缓存: 基于PerpetualCache 的 HashMap本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该Session中的所有 ...
- 聊聊MyBatis缓存机制
https://tech.meituan.com/mybatis_cache.html 前言 MyBatis是常见的Java数据库访问层框架.在日常工作中,开发人员多数情况下是使用MyBatis的默认 ...
- 【转】MyBatis缓存机制
转载:https://blog.csdn.net/bjweimengshu/article/details/79988252. 本文转载自公众号 美团技术点评 前言 MyBatis是常见的Java数据 ...
- MyBatis 缓存机制(十三)
什么是缓存 缓存就是内存中的一个对象,用于对数据库查询结果的保存,用于减少与数据库的交互次数从而降低数据库的压力,进而提高响应速度. MyBatis 缓存机制原理 Mybatis 缓存机制原理是将第一 ...
- 开源框架是如何使用设计模式的-MyBatis缓存机制之装饰者模式
写在前面 聊一聊MyBatis是如何使用装饰者模式的,顺便回顾下缓存的相关知识,可以看看右侧目录一览内容概述. 装饰者模式 这里就不了它的概念了,总结下就是套娃.利用组合的方式将装饰器组合进来,增强共 ...
- MyBatis缓存机制-二级缓存
MyBatis二级缓存是基于namespace级别的缓存. 1.MyBatis的缓存机制整体设计以及二级缓存的工作模式 如上图所示,当开一个会话时,一个SqlSession对象会使用一个Executo ...
- Mybatis——缓存机制
MyBatis 包含一个非常强大的查询缓存特性,它可以非常方便地配置和定制.缓存可以极大的提升查询效率. MyBatis系统中默认定义了两级缓存. 一级缓存和二级缓存. 1.默认情况下,只有一级缓存( ...
随机推荐
- API网关spring cloud gateway和负载均衡框架ribbon实战
通常我们如果有一个服务,会部署到多台服务器上,这些微服务如果都暴露给客户,是非常难以管理的,我们系统需要有一个唯一的出口,API网关是一个服务,是系统的唯一出口.API网关封装了系统内部的微服务,为客 ...
- 老技术记录-C#+SqlServer使用SqlDependency监听数据库表变化
开发环境: .net / C# (.net core理论上也可以) 数据库:MS SQL Server 2005 以上 (我用的sqlserver2012) 功能:SqlDependency提供了一种 ...
- python学习第五十天shutil模块的用法
什么shutil模块,就是对高级的文件,文件夹,压缩包进行处理的模块,下面简单讲述其用法. 文件和文件夹的操作 拷贝文件内容 import shutil shutil.copyfileobj(open ...
- 除了a链接跳转,还有其他的跳转方式
一.直接在要跳转部分加上onclick事件 1.加入onclick事件: <div onclick="window.open('http://baidu.com','_blank')& ...
- vi编辑器没有颜色的解决办法
Centos里的VI只默认安装了vim-minimal-7.x.所以无论是输入vi或者vim查看文件,syntax功能都无法正常启用.因此需要用yum安装另外两个组件:vim-common-7.x和v ...
- JSZip
/*! JSZip - A Javascript class for generating and reading zip files<http://stuartk.com/jszip> ...
- Raven2
Raven2实验 0x01 寻找IP 本机IP:56.130 1. 使用 nmap -sn "ip6"#主机发现(不进行端口扫描) https://cloud.tencent.c ...
- linux测试 Sersync 是否正常
[root@SERSYNC web]# for i in {1..10000};do echo 123456 > /data/web/$i &>/dev/null;do ne [r ...
- 【转】SIP协议 会话发起协议
转自:https://www.cnblogs.com/gardenofhu/p/7299963.html 会话发起协议(SIP)是VoIP技术中最常用的协议之一.它是一种应用层协议,与其他应用层协议协 ...
- [thinkphp 5.0源码阅读] 缓存(一)
保存缓存: user表数据: cache()方法保存缓存: 访问 http://mythinkphp.com/index/index/cache ,两个缓存被保存(runtime/cache目录下): ...