MyBatis 包含一个非常强大的查询缓存特性,它可以非常方便地配置和定制。缓存可以极大的提升查询效率。
MyBatis系统中默认定义了两级缓存, 一级 缓存和 二级缓存。
– 1、默认情况下,只有一级缓存(SqlSession级别的缓存,也称为本地缓存)开启,一级缓存默认实现类org.apache.ibatis.cache.impl.PerpetualCache。
– 2、二级缓存需要手动开启和配置,他是基于namespace级别的缓存。
– 3、为了提高扩展性。MyBatis定义了缓存接口Cache,我们可以通过实现Cache接口来自定义二级缓存。

一级缓存

一级缓存是Local Cache,即本地缓存,默认作用域为SqlSesson级别,mybatis3.1之后, 可以配置本地缓存的作用域(SESSION|STATEMENT),在全局配置文件中可以设置localCacheScope。Mybatis默认的一级缓存默认是通过org.apache.ibatis.cache.impl.PerpetualCache来实现的,PerpetualCache内里有一个HashMap,用来存储本地缓存。

Map的CacheKey由方法的ID,RowBounds,SQL语句,参数,环境因素影响;Map的Value存放具体的结果对象。

格式:影响因子的HashCode1:影响因子的HashCode2:方法ID:offset:limit:SQL语句:参数:环境ID

-1623117942:1735139101:com.kancy.mapper.PersonMapper.selectPersonById:0:2147483647:select * from t_person where id = ? and last_name = ? and sex = ?:1:emma:0:test

public CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql) {
if (closed) {
throw new ExecutorException("Executor was closed.");
}
CacheKey cacheKey = new CacheKey();
cacheKey.update(ms.getId());
cacheKey.update(rowBounds.getOffset());
cacheKey.update(rowBounds.getLimit());
cacheKey.update(boundSql.getSql());
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
TypeHandlerRegistry typeHandlerRegistry = ms.getConfiguration().getTypeHandlerRegistry();
// mimic DefaultParameterHandler logic
for (ParameterMapping parameterMapping : parameterMappings) {
if (parameterMapping.getMode() != ParameterMode.OUT) {
Object value;
String propertyName = parameterMapping.getProperty();
if (boundSql.hasAdditionalParameter(propertyName)) {
value = boundSql.getAdditionalParameter(propertyName);
} else if (parameterObject == null) {
value = null;
} else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
value = parameterObject;
} else {
MetaObject metaObject = configuration.newMetaObject(parameterObject);
value = metaObject.getValue(propertyName);
}
cacheKey.update(value);
}
}
if (configuration.getEnvironment() != null) {
// issue #176
cacheKey.update(configuration.getEnvironment().getId());
}
return cacheKey;
}

从查询的源码可以看出,mybatis在查询前,先看是否需要清除缓存,再通过CacheKey从缓存中查找是否有对应的key,有则返回对象,无则从数据库中查找,再看一级缓存的作用域范围,是STATEMENT则清除缓存,否则将结果集放到缓存中。

public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());
if (closed) {
throw new ExecutorException("Executor was closed.");
}
if (queryStack == 0 && ms.isFlushCacheRequired()) {
clearLocalCache();
}
List<E> list;
try {
queryStack++;
list = resultHandler == null ? (List<E>)

localCache.getObject(key)

 : null;
if (list != null) {
handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
} else
{
list =
queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
}

} finally {
queryStack--;
}
if (queryStack == 0) {
for (DeferredLoad deferredLoad : deferredLoads) {
deferredLoad.load();
}
// issue #601
deferredLoads.clear();
if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
// issue #482
clearLocalCache();
}
}
return list;
}

一级缓存演示& & 失效情况

同一次会话期间只要查询过的数据都会保存在当前SqlSession的一个Map中
一级缓存失效的四种情况
– 1、不同的SqlSession对应不同的一级缓存
– 2、同一个SqlSession但是查询条件不同
– 3、同一个SqlSession两次查询期间执行了任何一次增删改操作
– 4、同一个SqlSession两次查询期间手动清空了缓存

注意:

– sql标签的flushCache属性查询默认flushCache=false;增删改insert|update|delete会修改数据,默认flushCache=true,会同时清空一级和二级缓存。
– sqlSession.clearCache():只是用来清除一级缓存,不会清除二级缓存。
– 当在某一个作用域 (一级缓存Session/二级缓存Namespaces) 进行了 C/U/D 操作后,默认该作用域下所有有select中的缓存将被clear。

二级缓存

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

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

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

随机推荐

  1. Handling Configuration Changes with Fragments

    This post addresses a common question that is frequently asked on StackOverflow: What is the best wa ...

  2. php 判断访问是否是手机或者pc

    php代码 function isMobile() { $user_agent = $_SERVER['HTTP_USER_AGENT']; $mobile_agents = Array(" ...

  3. oracle体系结构基础

    摘自:http://jianshi-dlw.iteye.com/blog/1554892 Oracle的体系结构大体上分为两部分:Instance(实例)和Database(数据库). Instanc ...

  4. 阶段1 语言基础+高级_1-3-Java语言高级_04-集合_01 Collection集合_4_Iterator接口介绍

    collection集合中是没有索引的,不能使用普通的循环来便利它. 也是在util的包中 先判断集合中有没有元素 有元素就取出来,用next方法 使用接口来接受一个实现类,这就是多态

  5. Jmeter之CSV Data Set Config

    在很多情况下,需要针对测试数据做参数化操作,Jmeter提供了很好用的CSV Data Set Config插件. 一.界面显示 二.界面说明 1.名称:标识,建议设置为该组件是提供什么功能 2.注释 ...

  6. jmeter逻辑控制器详解(2)

    逻辑控制器 8.Runtime Controller 运行周期控制器,顾名思义,这是一种设置运行时间的控制器,它的效果就是使该控制器下的子项运行时间为[Runtime]中的数值(单位:s). Runt ...

  7. 嗯,python

    总觉得在这么个地方已经没有在碰blog的可能了...但是... 突然说要用python来配置环境...好歹也是这个专业的啊...还是 看看吧... 然后 百度一搜,看到一个 好的 网站,不知道 我一旦 ...

  8. JAVA AOP面向切面编程与动态代理

    1.静态代理和动态代理的概念:   在我的另一篇博文:Java 静态代理和动态代理 中有讲到,这里就不做赘述了. JDK动态代理它的好处理是可以为我们生成任何一个接口的代理类,并将需要增强的方法织入到 ...

  9. TensorFlow学习笔记8-深度学习的正则化

    深度学习的正则化 回顾一些基本概念 概念 描述 设计矩阵 数据集在特征向量上的表示 训练误差 学习到的模型与训练集标签之间的误差 泛化误差(测试误差) 学习到的模型与测试集之间的误差 欠拟合 模型的训 ...

  10. linux启动内核源码分析

    内核的启动时从main.c这个文件里面的start_kernel函数开始的,这个文件在linux源码里面的init文件夹下面 下面我们来看看这个函数 这个函数很长,可以看个大概过去 asmlinkag ...