Configuration 中缓存容器:
protected final Mapcaches = new StrictMap<>("Caches collection");
缓存类型别名初始化
XmlMapperBuilder 解析对应mapper二级缓存的初始化配置
try { String namespace = context.getStringAttribute("namespace"); if (namespace == null || namespace.equals("")) { throw new BuilderException("Mapper's namespace cannot be empty"); } builderAssistant.setCurrentNamespace(namespace); // 添加缓存对象 cacheRefElement(context.evalNode("cache-ref")); // 解析 cache 属性,添加缓存对象 cacheElement(context.evalNode("cache")); // 创建 ParameterMapping 对象 parameterMapElement(context.evalNodes("/mapper/parameterMap")); // 创建 ListresultMapElements(context.evalNodes("/mapper/resultMap")); // 解析可以复用的SQL sqlElement(context.evalNodes("/mapper/sql")); // 解析增删改查标签,得到 MappedStatement >> 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); } }
添加到缓存容器中
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);
currentCache = cache;
return cache;
}
一级缓存默认开启,一级缓存是在执行器中实现的
baseExcutor中一级缓存逻辑
@SuppressWarnings("unchecked") @Override publicList query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException { // 异常体系之 ErrorContext 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()) { // flushCache="true"时,即使是查询,也清空一级缓存 clearLocalCache(); } List list; try { // 防止递归查询重复处理缓存 queryStack++; // 查询一级缓存 // ResultHandler 和 ResultSetHandler的区别 list = resultHandler == null ? (List ) 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; }
PerpetualCache 实现一级缓存数据存储
二级缓存是在通过装饰器实现的,如果对应的mappedStatement有配置二级缓存,执行时先通过二级缓存对象对执行器进行装饰
二级缓存全局配置:
在settings :cacheEnable =true
对应的mapper个性化配置
两个都加了对应的mapper二级缓存就生效了
如果mapper中某个节点不需要缓存,加配置 useCache = false
获取SqlSession
DefualtSqlSessionFactory @Override public SqlSession openSession() { return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false); } private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) { Transaction tx = null; try { final Environment environment = configuration.getEnvironment(); // 获取事务工厂 final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment); // 创建事务 tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit); // 根据事务工厂和默认的执行器类型,创建执行器 >> final Executor executor = configuration.newExecutor(tx, execType); return new DefaultSqlSession(configuration, executor, autoCommit); } catch (Exception e) { closeTransaction(tx); // may have fetched a connection so lets call close() throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e); } finally { ErrorContext.instance().reset(); } }
二级缓存装饰位置
创建执行器时,判断如果二级缓存打开,用缓存对象装饰执行器,判断插件存在,用插件装饰执行器,返回
public Executor newExecutor(Transaction transaction, ExecutorType executorType) { executorType = executorType == null ? defaultExecutorType : executorType; executorType = executorType == null ? ExecutorType.SIMPLE : executorType; Executor executor; if (ExecutorType.BATCH == executorType) { executor = new BatchExecutor(this, transaction); } else if (ExecutorType.REUSE == executorType) { executor = new ReuseExecutor(this, transaction); } else { // 默认 SimpleExecutor executor = new SimpleExecutor(this, transaction); } // 二级缓存开关,settings 中的 cacheEnabled 默认是 true if (cacheEnabled) { executor = new CachingExecutor(executor); } // 植入插件的逻辑,至此,四大对象已经全部拦截完毕 executor = (Executor) interceptorChain.pluginAll(executor); return executor; }
CacheExcutor中执行二级缓存处理
// 先执行缓存处理逻辑,再真正调用实际执行器处理JDBC SQL相关 *** 作 @Override publicList query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException { Cache cache = ms.getCache(); // cache 对象是在哪里创建的? XMLMapperBuilder类 xmlconfigurationElement() // 由 标签决定 if (cache != null) { // flushCache="true" 清空一级二级缓存 >> flushCacheIfRequired(ms); if (ms.isUseCache() && resultHandler == null) { ensureNoOutParams(ms, boundSql); // 获取二级缓存 // 缓存通过 TransactionalCacheManager、TransactionalCache 管理 @SuppressWarnings("unchecked") List list = (List ) tcm.getObject(cache, key); if (list == null) { list = delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql); // 写入二级缓存 tcm.putObject(cache, key, list); // issue #578 and #116 } return list; } } // 走到 SimpleExecutor | ReuseExecutor | BatchExecutor return delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql); }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)