当前位置: 首页 > 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;}    
    }
    
http://www.lryc.cn/news/224549.html

相关文章:

  • 如何在 HarmonyOS 对数据库进行备份,恢复与加密
  • js实现向上、向下、向左、向右无缝滚动
  • 6 Hive引擎集成Apache Paimon
  • 发布版本自动化记录版本功能方法
  • Elastic Stack 8.11:引入一种新的强大查询语言 ES|QL
  • wx:for-item wx:for-index wx:for-key
  • 老师还不会评课?这里有你需要的解决方案
  • Talk | 马里兰大学博士生吴曦旸:分布式多智能体强化学习在复杂交通轨迹规划中的应用
  • 2023年下半年架构案例真题及答案
  • Java必考面试题,谈谈你对 Spring AOP 的理解
  • BERT和ChatGPT简单对比
  • 又一重要合作,创邻科技华为云联营产品正式发布
  • PHP+Swoole应用示例
  • 3线硬件SPI+DMA驱动 HX8347 TFT屏
  • 实验语音学的基本概念
  • 市场上ios签名公司做什么的?
  • 12. 一文快速学懂常用工具——docker 命令
  • API低代码开发应用场景
  • 从零开始搭建React+TypeScript+webpack开发环境-性能优化
  • sCrypt 现在支持 Ordinals 了
  • 乌班图搭建 LAMP
  • 【Unity细节】Unity中的Transform.SetParent还有你不知道的细节
  • php生成个性二维码
  • css排版—— 一篇优雅的文章(中英文) vs 聊天框的特别排版
  • 2022最新版-李宏毅机器学习深度学习课程-P46 自监督学习Self-supervised Learning(BERT)
  • 【MySQL习题】各个视频的平均完播率【全网最详细教学】
  • Linux Centos配置邮件发送
  • 宋浩高等数学笔记(三)微分中值定理
  • 华为认证 | 11月底这门HCIP认证即将发布!
  • U-Mail邮件系统安全登录解决方案