mybatis缓存
执行sql,需用SqlSession,就类似jdbc jdbc: 1.获取驱动 Drever.get(XXXX); 2.获取链接connection; 3.statement,prestatement进行sql语句与参数拼装 4.到数据库执行 5.ResultSet返回, 6.实体映射封装返回 mybatis其实就是把statement,prestatement给封装了下 mybatis: 1.执行器Executor:SQL执行过程的总体控制 2、StatementHandler:语句处理器负责和JDBC层具体交互,包括prepare语句,执行语句 3、ParameterHandler:参数处理器负责PreparedStatement入参的具体设置 4、ResultSetHandler:结果处理器负责将JDBC查询结果映射到java对象
tips:二级缓存放在了Map里面 详情看下面的源码






以下是mybatis源码:
@Override
public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
BoundSql boundSql = ms.getBoundSql(parameter);
//创建一级缓存
CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);
return query(ms, parameter, rowBounds, resultHandler, key, boundSql);
}
@Override
public CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql) {
//判断执行器是否关闭
if (closed) {
throw new ExecutorException("Executor was closed.");
}
CacheKey cacheKey = new CacheKey();
//1、将Statement中的id添加到CacheKey对象中的updateList属性 ,这个ID是某个方法所在的dAO(持久层方法全路径)
cacheKey.update(ms.getId());
//2、将offset(分页偏移量)添加到CacheKey对象中的updateList属性(如果没有分页则默认0)
cacheKey.update(rowBounds.getOffset());
//3、将limit(每页显示的条数)添加到CacheKey对象中的updateList属性(如果没有分页则默认Integer.MAX_VALUE)
cacheKey.update(rowBounds.getLimit());
//4、将sql语句(包括占位符?)添加到CacheKey对象中的updateList属性
cacheKey.update(boundSql.getSql());
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
TypeHandlerRegistry typeHandlerRegistry = ms.getConfiguration().getTypeHandlerRegistry();
// mimic DefaultParameterHandler logic
//5、循环用户传入的参数,并将每个参数添加到CacheKey对象中的updateList属性
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
//6、如果有配置Environment,则将Environment中的id添加到CacheKey对象中的updateList属性
cacheKey.update(configuration.getEnvironment().getId());
}
return cacheKey;
}
@SuppressWarnings("unchecked")
@Override
public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());
//执行器关闭
if (closed) {
throw new ExecutorException("Executor was closed.");
}
//查询次数为0,或者需要清除缓存属性为true:清楚本地缓存(一级缓存)
if (queryStack == 0 && ms.isFlushCacheRequired()) {
clearLocalCache();
}
List<E> list;
try {
queryStack++;
//结果处理器为空,从缓存获取
list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;
if (list != null) {
//缓存list不为空,从缓存获取
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;
}
//缓存获取 对应://缓存list不为空,从缓存获取
private void handleLocallyCachedOutputParameters(MappedStatement ms, CacheKey key, Object parameter, BoundSql boundSql) {
if (ms.getStatementType() == StatementType.CALLABLE) {
final Object cachedParameter = localOutputParameterCache.getObject(key);
if (cachedParameter != null && parameter != null) {
final MetaObject metaCachedParameter = configuration.newMetaObject(cachedParameter);
final MetaObject metaParameter = configuration.newMetaObject(parameter);
for (ParameterMapping parameterMapping : boundSql.getParameterMappings()) {
if (parameterMapping.getMode() != ParameterMode.IN) {
final String parameterName = parameterMapping.getProperty();
final Object cachedValue = metaCachedParameter.getValue(parameterName);
metaParameter.setValue(parameterName, cachedValue);
}
}
}
}
}
//从数据库获取
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 {
//清除缓存
localCache.removeObject(key);
}
//数据库结果重新放入缓存
localCache.putObject(key, list);
if (ms.getStatementType() == StatementType.CALLABLE) {
//放入Map
localOutputParameterCache.putObject(key, parameter);
}
return list;
}
解释数据库里面那个localOutputParameterCache参数,这个参数最终操作是放入Map
protected PerpetualCache localOutputParameterCache;
@Override
public void putObject(Object key, Object value) {
cache.put(key, value);
}
private final Map<Object, Object> cache = new HashMap<>();
本文来自博客园,作者:余生请多指教ANT,转载请注明原文链接:https://www.cnblogs.com/wangbiaohistory/p/15817554.html

浙公网安备 33010602011771号