【mybatis源码学习】缓存机制
一、mybatis的缓存
一级缓存:sqlsession级别,默认开启(一个事务内有效),该缓存无法通过配置关闭。如需关系需要显示调用sqlseesion.clearCache
二级缓存: sqlsessionFactory级别,需要手动开启,在xml配置cache节点(依赖事务的执行结果,对缓存进行刷新,也可以在具体的sql节点上做配置)
二、mybatis的缓存流程示意图
二、mybatis的缓存详细说明
1、cacheKey的组成部分
(1)cacheKey的组装内容
接口名+方法名+分页信息+sql语句+参数列表+数据库环境ID
(2)组装cacheKey的方法
public CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql) { if (closed) { throw new ExecutorException("Executor was closed."); } CacheKey cacheKey = new CacheKey(); cacheKey.update(ms.getId()); cacheKey.update(rowBounds.getOffset()); cacheKey.update(rowBounds.getLimit()); 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 cacheKey.update(configuration.getEnvironment().getId()); } return cacheKey; }
2、一级缓存
(1)一级缓存和sqlSession绑定,出现写操作之前,会对一级缓存全部清理。
(2)一级缓存是一个hashMap结构
3、二级缓存
(1)一个命名空间对应一个二级缓存,多个命名空间可以共享一个二级缓存。
(2)二级缓存开启会使用:org.apache.ibatis.executor.CachingExecutor
(3)二级缓存如何保障缓存一致性:
org.apache.ibatis.cache.TransactionalCacheManager
org.apache.ibatis.cache.decorators.TransactionalCache