执行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<>();