当前位置: 首页 > news >正文

Mybatis二级缓存源码整理

  1. 添加配置
    mybatis-plus.configuration.cache-enabled=true
    
  2. 在mapper.xml文件中添加cache标签
    <cache size="10240" eviction="LRU"/>
    
  3. 同一个事务中二级缓存不生效,会使用一级缓存,因为事务未提交。
执行流程部分
  1. Configuration创建Executor对象
    public class Configuration{public Executor newExecutor(Transaction transaction, ExecutorType executorType) {executorType = executorType == null ? defaultExecutorType : executorType;Executor executor = new SimpleExecutor(this, transaction);// 根据settings中配置的启用cache创建CachingExecutor包装类if (cacheEnabled) {executor = new CachingExecutor(executor);}return (Executor) interceptorChain.pluginAll(executor);}
    }
    
  2. CachingExecutor#query查询逻辑
    public class CachingExecutor implements Executor {public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler,CacheKey key, BoundSql boundSql) throws SQLException {//1. 从 MappedStatement中获取二级缓存对象,如果存在,则进入缓存查询逻辑Cache cache = ms.getCache();if (cache != null) {flushCacheIfRequired(ms);if (ms.isUseCache() && resultHandler == null) {ensureNoOutParams(ms, boundSql);List<E> list = (List<E>) tcm.getObject(cache, key);if (list == null) {list = delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);//2. 将数据保存到缓存中,注意这里先放入TransactionalCache对象中,等待事务提交时回调CachingExecutor#commit时,// 调用TransactionalCache#commit -> 调用flushPendingEntries将缓存数据写入到cache中,// 所以同一个事务中多次查询无法使用二级缓存中的数据tcm.putObject(cache, key, list); // issue #578 and #116}return list;}}// 3. 非二级缓存逻辑return delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);}    
    }
    
  3. TransactionalCache#commit事务提交时回调逻辑
    public class TransactionalCache{// 事务体骄傲时回调函数 public void commit() {if (clearOnCommit) {delegate.clear();}flushPendingEntries();reset();}private void flushPendingEntries() {for (Map.Entry<Object, Object> entry : entriesToAddOnCommit.entrySet()) {// 将缓存数据写入到cache对象中 delegate.putObject(entry.getKey(), entry.getValue());}for (Object entry : entriesMissedInCache) {if (!entriesToAddOnCommit.containsKey(entry)) {delegate.putObject(entry, null);}}}
    }
    

解析注册部分

XMLMapperBuilder解析MapperStatement并放入到Configuration中
  1. XMLMapperBuilder#configurationElement业务逻辑处理
    public class XMLMapperBuilder{private void configurationElement(XNode context) {try {String namespace = context.getStringAttribute("namespace");if (namespace == null || namespace.isEmpty()) {throw new BuilderException("Mapper's namespace cannot be empty");}builderAssistant.setCurrentNamespace(namespace);cacheRefElement(context.evalNode("cache-ref"));// 1. 解析XXXMapper.xml文件中的cache标签,并调用builderAssistant.useNewCache构建Cache实例cacheElement(context.evalNode("cache"));parameterMapElement(context.evalNodes("/mapper/parameterMap"));resultMapElements(context.evalNodes("/mapper/resultMap"));sqlElement(context.evalNodes("/mapper/sql"));// 2. 构建Statement对象buildStatementFromContext(context.evalNodes("select|insert|update|delete"));} catch (Exception e) {throw new BuilderException("Error parsing Mapper XML. The XML location is '" + resource + "'. Cause: " + e, e);}}    private void buildStatementFromContext(List<XNode> list, String requiredDatabaseId) {for (XNode context : list) {final XMLStatementBuilder statementParser = new XMLStatementBuilder(configuration, builderAssistant, context, requiredDatabaseId);// 构建Statement对象statementParser.parseStatementNode();}}
    }
    
XMLMapperBuilder#cacheElement 展开细节
  1. MapperBuilderAssistant#useNewCache构建Cache实例并添加到Configuration中缓存
    public class MapperBuilderAssistant{public Cache useNewCache(Class<? extends Cache> typeClass, Class<? extends Cache> evictionClass, Long flushInterval,Integer size, boolean readWrite, boolean blocking, Properties props) {Cache cache = new CacheBuilder(currentNamespace).implementation(valueOrDefault(typeClass, PerpetualCache.class)).addDecorator(valueOrDefault(evictionClass, LruCache.class)).clearInterval(flushInterval).size(size).readWrite(readWrite).blocking(blocking).properties(props).build();configuration.addCache(cache);// 将cache实例赋值给MapperBuilderAssistant对象的 currentCache 属性currentCache = cache;return cache;}    
    }
    
XMLStatementBuilder#parseStatementNode 展开细节
  1. XMLStatementBuilder#parseStatementNode调用builderAssistant.addMappedStatement实例化MapperStatement对象
    public class XMLStatementBuilder extends BaseBuilder {public void parseStatementNode() {// 省略部分代码 builderAssistant.addMappedStatement(id, sqlSource, statementType, sqlCommandType, fetchSize, timeout, parameterMap,parameterTypeClass, resultMap, resultTypeClass, resultSetTypeEnum, flushCache, useCache, resultOrdered,keyGenerator, keyProperty, keyColumn, databaseId, langDriver, resultSets, dirtySelect);}
    }
    
  2. MapperBuilderAssistant#addMappedStatement
    public class MapperBuilderAssistant extends BaseBuilder {public MappedStatement addMappedStatement(String id, SqlSource sqlSource, StatementType statementType,SqlCommandType sqlCommandType, Integer fetchSize, Integer timeout, String parameterMap, Class<?> parameterType,String resultMap, Class<?> resultType, ResultSetType resultSetType, boolean flushCache, boolean useCache,boolean resultOrdered, KeyGenerator keyGenerator, String keyProperty, String keyColumn, String databaseId,LanguageDriver lang, String resultSets, boolean dirtySelect) {id = applyCurrentNamespace(id, false);MappedStatement.Builder statementBuilder = new MappedStatement.Builder(configuration, id, sqlSource, sqlCommandType).resource(resource).fetchSize(fetchSize).timeout(timeout).statementType(statementType).keyGenerator(keyGenerator).keyProperty(keyProperty).keyColumn(keyColumn).databaseId(databaseId).lang(lang).resultOrdered(resultOrdered).resultSets(resultSets).resultMaps(getStatementResultMaps(resultMap, resultType, id)).resultSetType(resultSetType).flushCacheRequired(flushCache).useCache(useCache)//1. 将MapperBuilderAssistant对象的 currentCache 属性放入到cache字段中.cache(currentCache).dirtySelect(dirtySelect);ParameterMap statementParameterMap = getStatementParameterMap(parameterMap, parameterType, id);if (statementParameterMap != null) {statementBuilder.parameterMap(statementParameterMap);}MappedStatement statement = statementBuilder.build();configuration.addMappedStatement(statement);return statement;}    
    }
    

相关文章:

Mybatis二级缓存源码整理

添加配置mybatis-plus.configuration.cache-enabledtrue在mapper.xml文件中添加cache标签<cache size"10240" eviction"LRU"/>同一个事务中二级缓存不生效&#xff0c;会使用一级缓存&#xff0c;因为事务未提交。 执行流程部分 Configuration创建…...

如何在 HarmonyOS 对数据库进行备份,恢复与加密

数据库备份与恢复 场景介绍 当应用在处理一项重要的操作&#xff0c;显然是不能被打断的。例如&#xff1a;写入多个表关联的事务。此时&#xff0c;每个表的写入都是单独的&#xff0c;但是表与表之间的事务关联性不能被分割。 如果操作的过程中出现问题&#xff0c;开发者可…...

js实现向上、向下、向左、向右无缝滚动

向左滚动 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevice-width, ini…...

6 Hive引擎集成Apache Paimon

更多Paimon数据湖内容请关注&#xff1a;https://edu.51cto.com/course/35051.html 在实际工作中&#xff0c;我们通查会使用Flink计算引擎去读写Paimon&#xff0c;但是在批处理场景中&#xff0c;更多的是使用Hive去读写Paimon&#xff0c;这样操作起来更加方便。 前面我们…...

发布版本自动化记录版本功能方法

# 安装commitizennpm install --save-dev commitizen# 初始化Conventional Commits规范适配器npx commitizen init cz-conventional-changelog --save-dev --save-exact最后一步&#xff0c;需要在package.json中添加一个script"scripts": {..., // 此处省略其它配置…...

Elastic Stack 8.11:引入一种新的强大查询语言 ES|QL

作者&#xff1a;Tyler Perkins, Ninoslav Miskovic, Gilad Gal, Teresa Soler, Shani Sagiv, Jason Burns Elastic Stack 8.11 引入了数据流生命周期、一种配置数据流保留和降采样&#xff08;downsampling&#xff09; 的简单方法&#xff08;技术预览版&#xff09;&#xf…...

wx:for-item wx:for-index wx:for-key

wx:for-item wx:for-item , 数组当前项的变量名,默认为 item 作用&#xff1a;使用 &#xff08;当前项变量名.属性名&#xff09; 取得属性值每一项 <view wx:for"{{array}}"><view>{{item.name item.age }}</view> </view>等同于 &…...

老师还不会评课?这里有你需要的解决方案

优点&#xff1a; 1.课件制作: 老师的PPT设计得很新颖&#xff0c;插入的音乐视频都非常贴合课堂内容&#xff0c;看得出老师非常用心地进行了设计。 2.教师素养&#xff1a;老师的语言丰富、朗读能力很出色、板书设计很工整。 3.教师风格: xx老师上课激情澎湃/非常有亲和力…...

Talk | 马里兰大学博士生吴曦旸:分布式多智能体强化学习在复杂交通轨迹规划中的应用

本期为TechBeat人工智能社区第545期线上Talk&#xff01; 北京时间11月09日(周四)20:00&#xff0c;马里兰大学博士生—吴曦旸的Talk已准时在TechBeat人工智能社区开播&#xff01; 他与大家分享的主题是: “分布式多智能体强化学习在复杂交通轨迹规划中的应用”&#xff0c;介…...

2023年下半年架构案例真题及答案

案例的考点&#xff1a; 大数据架构 Lambda架构和Kappa架构 jwt特点 数据持久层&#xff0c;Redis数据丢失&#xff0c;数据库读写分离方案 Hibernat架构 SysML七个关系&#xff0c;填需求图 大数据的必选题&#xff1a; 某网作为某电视台在互联网上的大型门户入口&#…...

Java必考面试题,谈谈你对 Spring AOP 的理解

大家好&#xff0c;我是伍六七。 今天我们来学习 Spring 框架中最重要的概念之一&#xff1a;AOP。 这是一个 Java 程序员必考的面试题&#xff0c;大家好好理解。我们开始正文。 AOP 的概念 Spring AOP 是 Java 程序员们面试经常被问到的一个问题&#xff0c;但 AOP&#…...

BERT和ChatGPT简单对比

OpenAI发布了第一个版本的GPT&#xff08;Generative Pretrained Transformer&#xff09;模型在2018年6月。 谷歌的BERT模型&#xff08;Bidirectional Encoder Representations from Transformers&#xff09;是在2018年10月发布的。 BERT和ChatGPT都是由人工智能研究实验室…...

又一重要合作,创邻科技华为云联营产品正式发布

近日&#xff0c;创邻科技旗下的“Galaxybase高性能图平台”正式入驻华为云云商店联营商品&#xff0c;创邻科技成为华为云在数据库与缓存领域的联营联运合作伙伴。通过联营联运模式&#xff0c;双方合作能够深入产品、生态、解决方案等多个领域&#xff0c;助力各行业用户数字…...

PHP+Swoole应用示例

**Swoole是一个C编写的基于异步事件驱动和协程的并行网络通信引擎&#xff0c;为PHP提供高性能网络编程支持** ## ⚙️ 快速启动 可以直接使用 [Docker](https://github.com/swoole/docker-swoole) 来执行Swoole的代码&#xff0c;例如&#xff1a; bash docker run --rm php…...

3线硬件SPI+DMA驱动 HX8347 TFT屏

3线硬件SPIDMA驱动 HX8347 TFT屏&#xff0c;实现用DMA清屏。 参考&#xff1a;基于stm32 标准库spi驱动st7789彩屏TFT(使用DMA)-技术天地-深圳市修德电子有限公司 一、源码 HX8347.h #ifndef USER_HX8347_H_ #define USER_HX8347_H_#define SPI_hardware #define SPI_hardw…...

实验语音学的基本概念

语音学 实验语音学只是语音学的一个分支&#xff0c;那么语音学到底是研究什么的呢&#xff1f;我们先有一个大致了解。 语音学是研究语言声音体系的学科。语音学的任务是研究说明语音的性质&#xff0c;内部结构和单位&#xff0c;语音的分类和组合&#xff0c;语音的产生、…...

市场上ios签名公司做什么的?

iOS签名公司是提供iOS应用程序签名服务的公司。它们为开发者提供了一种简单的方式来将他们的应用程序发布到iOS设备上&#xff0c;同时也为用户提供了一种下载和安装这些应用程序的方法。这些公司提供的签名服务包括苹果企业签名和开发者签名&#xff0c;其中企业签名是为企业开…...

12. 一文快速学懂常用工具——docker 命令

本章讲解知识点 Docker 引擎Docker 常用命令Docker 生命周期详解Containerd 与 Docker 命令对比本专栏适合于软件开发刚入职的学生或人士,有一定的编程基础,帮助大家快速掌握工作中必会的工具和指令。本专栏针对面试题答案进行了优化,尽量做到好记、言简意赅。如专栏内容有错…...

API低代码开发应用场景

什么是API低代码开发平台 API低代码开发平台是一种基于低代码开发的技术平台&#xff0c;它可以帮助企业快速构建和部署API应用程序。该平台通过提供可视化的开发工具、预定义的组件和模板、自动化的代码生成等功能&#xff0c;使得开发者可以在不需要编写大量代码的情况下&am…...

从零开始搭建React+TypeScript+webpack开发环境-性能优化

前言 当我们开发React应用时&#xff0c;性能始终是一个重要的考虑因素。随着应用规模的增长&#xff0c;React组件的数量和复杂性也会相应增加&#xff0c;这可能会导致性能问题的出现。在这篇博文中&#xff0c;我们将探讨如何通过一系列的技巧和最佳实践来优化React应用的性…...

从WWDC看苹果产品发展的规律

WWDC 是苹果公司一年一度面向全球开发者的盛会&#xff0c;其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具&#xff0c;对过去十年 WWDC 主题演讲内容进行了系统化分析&#xff0c;形成了这份…...

QMC5883L的驱动

简介 本篇文章的代码已经上传到了github上面&#xff0c;开源代码 作为一个电子罗盘模块&#xff0c;我们可以通过I2C从中获取偏航角yaw&#xff0c;相对于六轴陀螺仪的yaw&#xff0c;qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...

【网络安全产品大调研系列】2. 体验漏洞扫描

前言 2023 年漏洞扫描服务市场规模预计为 3.06&#xff08;十亿美元&#xff09;。漏洞扫描服务市场行业预计将从 2024 年的 3.48&#xff08;十亿美元&#xff09;增长到 2032 年的 9.54&#xff08;十亿美元&#xff09;。预测期内漏洞扫描服务市场 CAGR&#xff08;增长率&…...

SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现

摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序&#xff0c;以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务&#xff0c;提供稳定高效的数据处理与业务逻辑支持&#xff1b;利用 uniapp 实现跨平台前…...

基于Docker Compose部署Java微服务项目

一. 创建根项目 根项目&#xff08;父项目&#xff09;主要用于依赖管理 一些需要注意的点&#xff1a; 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件&#xff0c;否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...

从零实现STL哈希容器:unordered_map/unordered_set封装详解

本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说&#xff0c;直接开始吧&#xff01; 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...

select、poll、epoll 与 Reactor 模式

在高并发网络编程领域&#xff0c;高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表&#xff0c;以及基于它们实现的 Reactor 模式&#xff0c;为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。​ 一、I…...

2023赣州旅游投资集团

单选题 1.“不登高山&#xff0c;不知天之高也&#xff1b;不临深溪&#xff0c;不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...

HDFS分布式存储 zookeeper

hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架&#xff0c;允许使用简单的变成模型跨计算机对大型集群进行分布式处理&#xff08;1.海量的数据存储 2.海量数据的计算&#xff09;Hadoop核心组件 hdfs&#xff08;分布式文件存储系统&#xff09;&a…...

CRMEB 中 PHP 短信扩展开发:涵盖一号通、阿里云、腾讯云、创蓝

目前已有一号通短信、阿里云短信、腾讯云短信扩展 扩展入口文件 文件目录 crmeb\services\sms\Sms.php 默认驱动类型为&#xff1a;一号通 namespace crmeb\services\sms;use crmeb\basic\BaseManager; use crmeb\services\AccessTokenServeService; use crmeb\services\sms\…...