六、MyBatis-缓存机制
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-缓存机制的更多相关文章
- 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 包含一个非常强大的查询缓存特性,它可以非常方便地配置和定制.缓存可以极大的提升查询效率. MyBatis系统中默认定义了两级缓存. 一级缓存和二级缓存. 1.默认情况下,只有一级缓存( ...
- MyBatis缓存机制-二级缓存
MyBatis二级缓存是基于namespace级别的缓存. 1.MyBatis的缓存机制整体设计以及二级缓存的工作模式 如上图所示,当开一个会话时,一个SqlSession对象会使用一个Executo ...
随机推荐
- [BZOJ2822]:[AHOI2012]树屋阶梯(卡特兰数)
题目传送门 题目描述 暑假期间,小龙报名了一个模拟野外生存作战训练班来锻炼体魄,训练的第一个晚上,教官就给他们出了个难题.由于地上露营湿气重,必须选择在高处的树屋露营.小龙分配的树屋建立在一颗高度为N ...
- Mybatis传多个参数(三种解决方案) mapper.xml的sql语句修改!
第一种 Public User selectUser(String name,String area); 对应的Mapper.xml <select id="selectUser&qu ...
- el-date-picker用法
需求:1.默认时间是当天开始到此刻的时间 2.快捷键为今天.昨天.最近一周.最近30天.最近90天 3.不可以清空,必选项
- 查看Oracle数据库中的执行计划
1.set autotrace traceonly命令 2.explain plan for命令 1)explain plan for select * from dual; 2)select * f ...
- 使用innobackupex基于从库搭建级联从库及一两从
使用innobackupex基于从库搭建mysql主从架构 现有的架构是一主一从,版本为Mysql5.6.37.实施要求是:利用从库,搭建第二个从库,版本为5.7.21 主库:192.168.1.21 ...
- python实现格式化输出9*9乘法表
# python 9*9 乘法表 for i in range(1,10): for j in range(1,i+1): print("%s*%s=%s"%(i,j,i*j),e ...
- log4j.properties 输出指定类日志
比如,我只要众多日志中,红色框的日志,则可以指定类:com.dangdang.ddframe.rdb.sharding.parser.SQLParserFactory 修改配置文件: 再次输出结果为:
- SpringMVC学习01——HelloSpringMvc Demo
HelloWorldController.java文件 package com.su.controller; import org.springframework.stereotype.Control ...
- Linux 服务器安全优化
最小的权限+最少的服务=最大的安全 所以,无论是配置任何服务器,我们都必须把不用的服务关闭.把系统权限设置到最小,这样才能保证服务器最大的安全.下面是CentOS服务器安全设置,供大家参考. 一.注释 ...
- js面向对象程序设计之继承
在面向对象语言中继承分成两种:接口继承和实现继承.解释一下,接口继承只继承方法的签名,而实现继承则是继承实际的方法.但是ECMAScript中的函数没有签名所以无法进行接口继承,只能是实现实现继承.而 ...