Mybatis源码分析-一级缓存
来源:互联网 发布:如何删除mac下载程序 编辑:程序博客网 时间:2024/05/17 01:27
为了能提高系统性能,缓存必不可少,mybatis同样也是有缓存的!
分一级缓存和二级缓存,该篇介绍下一级缓存!!
我们回顾下配置阶段,再创建executor执行器时,有个Configuration.newExecutor方法,来看下
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 { executor = new SimpleExecutor(this, transaction); } //默认cacheEnabled为true,那么此时的执行器其实是CachingExecutor,将executor当参数传递给CachingExecutor,装饰了下,增加了缓存功能 if (cacheEnabled) { executor = new CachingExecutor(executor); } executor = (Executor) interceptorChain.pluginAll(executor); return executor; }
那么我们再执行Executor.query的时候,也就是说先调用CachingExecutor的query方法
public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException { BoundSql boundSql = ms.getBoundSql(parameterObject); //cachekey 即缓存的标识 CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql); return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql); }public CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql) { if (closed) { throw new ExecutorException("Executor was closed."); } CacheKey cacheKey = new CacheKey(); //StatementId cacheKey.update(ms.getId()); //自带分页参数数据 cacheKey.update(rowBounds.getOffset()); cacheKey.update(rowBounds.getLimit()); //sql语句 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//xml中environment的id cacheKey.update(configuration.getEnvironment().getId()); } //以上种种,组成一个缓存标识 return cacheKey; } public void update(Object object) { //生成hashcode,具体算法大家可以进去看,主要是分集合和非集合之分 int baseHashCode = object == null ? 1 : ArrayUtil.hashCode(object); count++; checksum += baseHashCode; //扩大count倍 baseHashCode *= count;//加上扩展固定值 hashcode = multiplier * hashcode + baseHashCode; updateList.add(object); }
好了 有了key,那么就应该从缓存中获取数据了,
public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException { ...省略 //获取缓存 list = resultHandler == null ? (List<E>) localCache.getObject(key) : null; ...判断是否为空 //为空,则从数据库中获取 list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql); ...省略 return list; } private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException { List<E> list; //标记下 localCache.putObject(key, EXECUTION_PLACEHOLDER); try { list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql); } finally { //每次都会移除 PerpetualCache 其实就是放到hashmap中 localCache.removeObject(key); } //在put进缓存 localCache.putObject(key, list); if (ms.getStatementType() == StatementType.CALLABLE) { localOutputParameterCache.putObject(key, parameter); } return list; }
好了 ,缓存是不是很简单,原来就是放到PerpetualCache类的hashmap中。
最后 session.close();关闭时,将localCache = null;缓存设置为null!!
也就是说 一级缓存的作用体现在同一个session中,一旦关闭,则清空,适合同一个session频繁的调用同样的sql(我想这种情况很少吧!)
而且,这种缓存的做法,默认状态是开启的,自动进行缓存,如果session长时间不关的话,会造成数据量越来越大,造成内存溢出!所以要及时关闭session哦!
阅读全文
0 0
- Mybatis源码分析-一级缓存
- <MyBatis缓存机制>一级缓存源码浅析
- MyBatis一级缓存
- Mybatis一级缓存
- Mybatis一级缓存
- MyBatis 一级缓存实现
- mybatis的一级缓存
- MyBatis-一级缓存
- mybatis一级缓存
- mybatis中一级缓存
- mybatis一级缓存
- mybatis的一级缓存
- MyBatis的一级缓存
- Mybatis一级缓存原理
- MyBatis一级缓存,二级缓存
- MyBatis 一级缓存,二级缓存
- MyBatis中的一级缓存
- Mybatis一级缓存 去除
- C++中的mutable和volatile
- LeetCode | 60. Permutation Sequence——第K个全排列
- PHP表单数据初步处理
- hashmap冲突的解决方法以及原理分析:
- 7.6--SSH学习之关联映射
- Mybatis源码分析-一级缓存
- Redis遍历所有key的两个命令 -- KEYS 和 SCAN
- Boost算法拓展---几种Boost方法
- 伪Ajax上传文件
- 剑指offer面试题[51]-数组中重复的数字
- nodejs学习笔记(1)
- Flink关系型API简介
- php 变量作用域出现的问题
- 5.乐观锁和悲观锁