当前位置: 首页 > 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应用的性…...

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…...

AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘

美国西海岸的夏天&#xff0c;再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至&#xff0c;这不仅是开发者的盛宴&#xff0c;更是全球数亿苹果用户翘首以盼的科技春晚。今年&#xff0c;苹果依旧为我们带来了全家桶式的系统更新&#xff0c;包括 iOS 26、iPadOS 26…...

Prompt Tuning、P-Tuning、Prefix Tuning的区别

一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销&#xff0c;平衡网络负载&#xff0c;延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

【WiFi帧结构】

文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成&#xff1a;MAC头部frame bodyFCS&#xff0c;其中MAC是固定格式的&#xff0c;frame body是可变长度。 MAC头部有frame control&#xff0c;duration&#xff0c;address1&#xff0c;address2&#xff0c;addre…...

CMake基础:构建流程详解

目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...

linux 错误码总结

1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

【配置 YOLOX 用于按目录分类的图片数据集】

现在的图标点选越来越多&#xff0c;如何一步解决&#xff0c;采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集&#xff08;每个目录代表一个类别&#xff0c;目录下是该类别的所有图片&#xff09;&#xff0c;你需要进行以下配置步骤&#x…...

Linux-07 ubuntu 的 chrome 启动不了

文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了&#xff0c;报错如下四、启动不了&#xff0c;解决如下 总结 问题原因 在应用中可以看到chrome&#xff0c;但是打不开(说明&#xff1a;原来的ubuntu系统出问题了&#xff0c;这个是备用的硬盘&a…...