缓存在互联网系统中是非常重要的, 其主要作用是将数据保存到内存中, 当用户查询数据 时, 优先从缓存容器中获取数据,而不是频繁地从数据库中查询数据,从而提高查询性能。目 前流行的缓存服务器有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缓存机制(转)的更多相关文章

  1. mybatis缓存机制

    目录 mybatis缓存机制 Executor和缓存 一级缓存 小结 二级缓存 小结 mybatis缓存机制 mybatis支持一.二级缓存来提高查询效率,能够正确的使用缓存的前提是熟悉mybatis ...

  2. 聊聊MyBatis缓存机制【美团-推荐】

    聊聊MyBatis缓存机制 2018年01月19日 作者: 凯伦 文章链接 18778字 38分钟阅读 前言 MyBatis是常见的Java数据库访问层框架.在日常工作中,开发人员多数情况下是使用My ...

  3. 《深入理解mybatis原理4》 MyBatis缓存机制的设计与实现

    <深入理解mybatis原理> MyBatis缓存机制的设计与实现 本文主要讲解MyBatis非常棒的缓存机制的设计原理,给读者们介绍一下MyBatis的缓存机制的轮廓,然后会分别针对缓存 ...

  4. Mybatis缓存机制及mybatis的各个组成部分

    Mybatis 一级缓存: 基于PerpetualCache 的 HashMap本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该Session中的所有 ...

  5. 聊聊MyBatis缓存机制

    https://tech.meituan.com/mybatis_cache.html 前言 MyBatis是常见的Java数据库访问层框架.在日常工作中,开发人员多数情况下是使用MyBatis的默认 ...

  6. 【转】MyBatis缓存机制

    转载:https://blog.csdn.net/bjweimengshu/article/details/79988252. 本文转载自公众号 美团技术点评 前言 MyBatis是常见的Java数据 ...

  7. MyBatis 缓存机制(十三)

    什么是缓存 缓存就是内存中的一个对象,用于对数据库查询结果的保存,用于减少与数据库的交互次数从而降低数据库的压力,进而提高响应速度. MyBatis 缓存机制原理 Mybatis 缓存机制原理是将第一 ...

  8. 开源框架是如何使用设计模式的-MyBatis缓存机制之装饰者模式

    写在前面 聊一聊MyBatis是如何使用装饰者模式的,顺便回顾下缓存的相关知识,可以看看右侧目录一览内容概述. 装饰者模式 这里就不了它的概念了,总结下就是套娃.利用组合的方式将装饰器组合进来,增强共 ...

  9. MyBatis缓存机制-二级缓存

    MyBatis二级缓存是基于namespace级别的缓存. 1.MyBatis的缓存机制整体设计以及二级缓存的工作模式 如上图所示,当开一个会话时,一个SqlSession对象会使用一个Executo ...

  10. Mybatis——缓存机制

    MyBatis 包含一个非常强大的查询缓存特性,它可以非常方便地配置和定制.缓存可以极大的提升查询效率. MyBatis系统中默认定义了两级缓存. 一级缓存和二级缓存. 1.默认情况下,只有一级缓存( ...

随机推荐

  1. 实现atoi

    1. 去掉首位空格 2. 判断首位是否有正负号 3. 判断各位是否是0~9,有其他字符直接返回当前结果   public class Solution { public int atoi(String ...

  2. IDEA Maven project: 'xxx/pom.xml' already exists in VFS

    Failed to create a Maven project: 'xxx/pom.xml' already exists in VFS idea创建项目后,发现项目有问题,删除后重新创建,提示错误 ...

  3. package.json说明

    package.json是什么? 直接的说:就是管理你本地安装的npm包 一个package.json文件可以做如下事情: 展示项目所依赖的npm包 允许你指定一个包的版本[范围] 让你建立起稳定,意 ...

  4. centos安装httprunner方法

    测试脚本执行的环境部署(在jenkins服务器中,要求jenkins服务器和目标的灰度环境是连通的): 一.安装python3.8 $python#看见2.6.6Python 2.6.6 (r266: ...

  5. usleep和sleep

    usleep 和 sleep 都是用于将进程挂起, 所不同的是前者在微秒级别, 后者在秒级别.

  6. spark复习笔记(3):使用spark实现单词统计

    wordcount是spark入门级的demo,不难但是很有趣.接下来我用命令行.scala.Java和python这三种语言来实现单词统计. 一.使用命令行实现单词的统计 1.首先touch一个a. ...

  7. 5-基于TMS320C6678+XC7K325T的6U CPCIe高性能处理平台

    基于TMS320C6678+XC7K325T的6U CPCIe高性能处理平台 一.板卡概述      本板卡系自主研发,基于CPCI 6U架构,符合CPCI2.0标准.采用 DSP TMS320C66 ...

  8. 一、C++类库与C#类库相互调用

    1.C++调用C#类库 1.准备C#类库(dll文件) 1.1.创建C#类库: 右击项目类库生成即可, 出现.dll(类库)与.pdb(pdb文件包含了编译后程序指向源代码的位置信息, 用于调试的时候 ...

  9. [译]深度学习(Yann LeCun)

    深度学习 严恩·乐库  约书亚•本吉奥  杰弗里·希尔顿 摘要深度学习是计算模型,是由多个处理层学习多层次抽象表示的数据.这些方法极大地提高了语音识别.视觉识别.物体识别.目标检测和许多其他领域如药物 ...

  10. NOIP原题板刷

    update 10.11 我可能已经刷完大部分了,可是这篇blog我也不想更了 这个人很懒,做了很多题但是不想写题解,也不想更blog,所以这篇blog又咕咕了. 把从 \(1997-2017\) 近 ...