以下SQL的执行为例,描述mybatis的SQL执行过程
public DataResponse
mybatis SQL首先通过JDK动态代理调用MapperProxy的invoke方法
public class MapperProxyimplements InvocationHandler, Serializable { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { try { if (Object.class.equals(method.getDeclaringClass())) { // Objec代理的方法执行 return method.invoke(this, args); } else { // 执行方法调用,一般都从这里开始调用 return cachedInvoker(method).invoke(proxy, method, args, sqlSession); } } catch (Throwable t) { throw ExceptionUtil.unwrapThrowable(t); } } @Override public Object invoke(Object proxy, Method method, Object[] args, SqlSession sqlSession) throws Throwable { return mapperMethod.execute(sqlSession, args); } }
mapperMethod.execute调用MapperMethod#execute,该方法根据不同的command.getType(),执行不同的SQL
public class MapperMethod { public Object execute(SqlSession sqlSession, Object[] args) { Object result; switch (command.getType()) { case INSERT: { // 插入 Object param = method.convertArgsToSqlCommandParam(args); result = rowCountResult(sqlSession.insert(command.getName(), param)); break; } case UPDATe: { // 更新 Object param = method.convertArgsToSqlCommandParam(args); result = rowCountResult(sqlSession.update(command.getName(), param)); break; } case DELETE: { // 删除 Object param = method.convertArgsToSqlCommandParam(args); result = rowCountResult(sqlSession.delete(command.getName(), param)); break; } case SELECT: // 查询 if (method.returnsVoid() && method.hasResultHandler()) { // 查询结果返回空并且有返回结果需要处理的情况 executeWithResultHandler(sqlSession, args); result = null; } else if (method.returnsMany()) { // 查询结果返回多条 result = executeForMany(sqlSession, args); } else if (method.returnsMap()) { // 查询结果返回Map result = executeForMap(sqlSession, args); } else if (method.returnsCursor()) { // 查询结果返回游标 result = executeForCursor(sqlSession, args); } else { // 查询结果返回单条记录 Object param = method.convertArgsToSqlCommandParam(args); result = sqlSession.selectOne(command.getName(), param); if (method.returnsOptional() && (result == null || !method.getReturnType().equals(result.getClass()))) { result = Optional.ofNullable(result); } } break; case FLUSH: // 刷新Statements result = sqlSession.flushStatements(); break; default: throw new BindingException("Unknown execution method for: " + command.getName()); } if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) { throw new BindingException("Mapper method '" + command.getName() + " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ")."); } return result; } }
executeForMany(sqlSession, args)方法首先将参数转化为SQL命令参数,然后使用sqlSession执行selectList
privateObject executeForMany(SqlSession sqlSession, Object[] args) { List result; //将参数转化为SQL命令参数 Object param = method.convertArgsToSqlCommandParam(args); if (method.hasRowBounds()) { RowBounds rowBounds = method.extractRowBounds(args); result = sqlSession.selectList(command.getName(), param, rowBounds); } else { // 执行selectList result = sqlSession.selectList(command.getName(), param); } // issue #510 Collections & arrays support if (!method.getReturnType().isAssignableFrom(result.getClass())) { if (method.getReturnType().isArray()) { return convertToArray(result); } else { return convertToDeclaredCollection(sqlSession.getConfiguration(), result); } } return result; }
sqlSession.selectList(command.getName(), param)方法会调用SqlSessionTemplate#selectList, 该方法调用代理
public class SqlSessionTemplate implements SqlSession, DisposableBean { publicList selectList(String statement, Object parameter) { // 调用到invoke方法 return this.sqlSessionProxy.selectList(statement, parameter); } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 获取SqlSession SqlSession sqlSession = getSqlSession(SqlSessionTemplate.this.sqlSessionFactory, SqlSessionTemplate.this.executorType, SqlSessionTemplate.this.exceptionTranslator); try { // 调用方法 Object result = method.invoke(sqlSession, args); if (!isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) { // 带事务时强制提交/回滚 // force commit even on non-dirty sessions because some databases require // a commit/rollback before calling close() sqlSession.commit(true); } return result; } catch (Throwable t) { Throwable unwrapped = unwrapThrowable(t); if (SqlSessionTemplate.this.exceptionTranslator != null && unwrapped instanceof PersistenceException) { // release the connection to avoid a deadlock if the translator is no loaded. See issue #22 closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory); sqlSession = null; Throwable translated = SqlSessionTemplate.this.exceptionTranslator .translateExceptionIfPossible((PersistenceException) unwrapped); if (translated != null) { unwrapped = translated; } } throw unwrapped; } finally { if (sqlSession != null) { closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory); } } } } }
method.invoke(sqlSession, args)会调用到DefaultSqlSession#selectList,selectList获取映射的Statements, 然后使用executor去执行查询
public class DefaultSqlSession implements SqlSession { @Override publicList selectList(String statement, Object parameter, RowBounds rowBounds) { try { // 获取映射的Statements MappedStatement ms = configuration.getMappedStatement(statement); // 使用executor去执行查询 return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER); } catch (Exception e) { throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e); } finally { ErrorContext.instance().reset(); } } }
获取映射的Statements调用了Configuration#getMappedStatement,该方法会从statements Map中根据id获取对应的statement,statements Map中的值在应用启动时,mybatis会加载
public class Configuration { public MappedStatement getMappedStatement(String id) { return this.getMappedStatement(id, true); } public MappedStatement getMappedStatement(String id, boolean validateIncompleteStatements) { if (validateIncompleteStatements) { buildAllStatements(); } return mappedStatements.get(id); } }
executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER)方法执行前会调用插件代理Plugin#invoke, 如常用的分页插件等
public class Plugin implements InvocationHandler { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { try { // 获取方法集合 Setmethods = signatureMap.get(method.getDeclaringClass()); if (methods != null && methods.contains(method)) { // 执行拦截器 return interceptor.intercept(new Invocation(target, method, args)); } return method.invoke(target, args); } catch (Exception e) { throw ExceptionUtil.unwrapThrowable(e); } } }
这里使用了PageHelper,他会拦截查询语句,先查出总的数据数,然后在查具体数据
public class PageInterceptor implements Interceptor { @Override public Object intercept(Invocation invocation) throws Throwable { try { Object[] args = invocation.getArgs(); MappedStatement ms = (MappedStatement) args[0]; Object parameter = args[1]; RowBounds rowBounds = (RowBounds) args[2]; ResultHandler resultHandler = (ResultHandler) args[3]; Executor executor = (Executor) invocation.getTarget(); CacheKey cacheKey; BoundSql boundSql; //由于逻辑关系,只会进入一次 if (args.length == 4) { //4 个参数时 boundSql = ms.getBoundSql(parameter); // 创建缓存的key cacheKey = executor.createCacheKey(ms, parameter, rowBounds, boundSql); } else { //6 个参数时 cacheKey = (CacheKey) args[4]; boundSql = (BoundSql) args[5]; } // 检查对话是否存在 checkDialectExists(); //对 boundSql 的拦截处理 if (dialect instanceof BoundSqlInterceptor.Chain) { // 绑定sql boundSql = ((BoundSqlInterceptor.Chain) dialect).doBoundSql(BoundSqlInterceptor.Type.ORIGINAL, boundSql, cacheKey); } List resultList; //调用方法判断是否需要进行分页,如果不需要,直接返回结果 if (!dialect.skip(ms, parameter, rowBounds)) { //判断是否需要进行 count 查询 if (dialect.beforeCount(ms, parameter, rowBounds)) { //动态拼接SQL,查询数据总数 Long count = count(executor, ms, parameter, rowBounds, null, boundSql); // 处理查询总数,返回 true 时继续分页查询,false 时直接返回 if (!dialect.afterCount(count, parameter, rowBounds)) { //当查询总数为 0 时,直接返回空的结果 return dialect.afterPage(new ArrayList(), parameter, rowBounds); } } // 查询数据列表 resultList = ExecutorUtil.pageQuery(dialect, executor, ms, parameter, rowBounds, resultHandler, boundSql, cacheKey); } else { //rowBounds用参数值,不使用分页插件处理时,仍然支持默认的内存分页 resultList = executor.query(ms, parameter, rowBounds, resultHandler, cacheKey, boundSql); } return dialect.afterPage(resultList, parameter, rowBounds); } finally { if(dialect != null){ dialect.afterAll(); } } } }
分页查询数据调用ExecutorUtil#pageQuery
public abstract class ExecutorUtil { public staticList pageQuery(Dialect dialect, Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql, CacheKey cacheKey) throws SQLException { //判断是否需要进行分页查询 if (dialect.beforePage(ms, parameter, rowBounds)) { //生成分页的缓存 key CacheKey pageKey = cacheKey; //处理参数对象 parameter = dialect.processParameterObject(ms, parameter, boundSql, pageKey); //调用方言获取分页 sql String pageSql = dialect.getPageSql(ms, boundSql, parameter, rowBounds, pageKey); BoundSql pageBoundSql = new BoundSql(ms.getConfiguration(), pageSql, boundSql.getParameterMappings(), parameter); Map additionalParameters = getAdditionalParameter(boundSql); //设置动态参数 for (String key : additionalParameters.keySet()) { pageBoundSql.setAdditionalParameter(key, additionalParameters.get(key)); } //对 boundSql 的拦截处理 if (dialect instanceof BoundSqlInterceptor.Chain) { pageBoundSql = ((BoundSqlInterceptor.Chain) dialect).doBoundSql(BoundSqlInterceptor.Type.PAGE_SQL, pageBoundSql, pageKey); } //执行分页查询 return executor.query(ms, parameter, RowBounds.DEFAULT, resultHandler, pageKey, pageBoundSql); } else { //不执行分页的情况下,也不执行内存分页 return executor.query(ms, parameter, RowBounds.DEFAULT, resultHandler, cacheKey, boundSql); } }
executor.query(ms, parameter, RowBounds.DEFAULT, resultHandler, pageKey, pageBoundSql)会调用CachingExecutor#query方法
public class CachingExecutor implements Executor { publicList query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException { Cache cache = ms.getCache(); if (cache != null) { // 缓存存在,从缓存里面取 flushCacheIfRequired(ms); if (ms.isUseCache() && resultHandler == null) { ensureNoOutParams(ms, boundSql); @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; // 缓存存在,直接返回 } } // 执行查询 return delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql); } }
delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql)会调用Executor#query方法,优先取缓存的值,如果缓存没有,再查询数据库
public abstract class baseExecutor implements Executor { @Override publicList 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."); } if (queryStack == 0 && ms.isFlushCacheRequired()) { clearLocalCache(); } List list; try { queryStack++; // 获取缓存值 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; } // 从数据库查询数据 private List queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException { List 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) { localOutputParameterCache.putObject(key, parameter); } return list; } }
doQuery(ms, parameter, rowBounds, resultHandler, boundSql)会根据配置调用实现了baseExecutor的子类,子类有:BatchExecutor、ClosedExecutor、ResueExecutor和SimpleExecutor
一般使用的是SimpleExecutor, 他的doQuery方法如下
public class SimpleExecutor extends baseExecutor { publicList doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException { Statement stmt = null; try { // 获取配置 Configuration configuration = ms.getConfiguration(); // 生成StatementHandler StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql); // 预处理Statement stmt = prepareStatement(handler, ms.getStatementLog()); // 执行查询 return handler.query(stmt, resultHandler); } finally { closeStatement(stmt); } } }
handler.query(stmt, resultHandler)首先调用RoutingStatementHandler#query,这里会代理到PreparedStatementHandler#query
public class RoutingStatementHandler implements StatementHandler { @Override publicList query(Statement statement, ResultHandler resultHandler) throws SQLException { return delegate.query(statement, resultHandler); } }
public class PreparedStatementHandler extends baseStatementHandler { @Override publicList query(Statement statement, ResultHandler resultHandler) throws SQLException { // 转化为PreparedStatement PreparedStatement ps = (PreparedStatement) statement; // 执行sql ps.execute(); // 处理结果集 return resultSetHandler.handleResultSets(ps); } }
ps.execute()会调用到DruidPooledPreparedStatement#execute
public class DruidPooledPreparedStatement extends DruidPooledStatement implements PreparedStatement { @Override public boolean execute() throws SQLException { // 开启检查 checkOpen(); // 增加执行计数器 incrementExecuteCount(); // 事务记录 transactionRecord(sql); // 执行之前处理 conn.beforeExecute(); try { // 执行SQL return stmt.execute(); } catch (Throwable t) { errorCheck(t); throw checkException(t); } finally { // 执行之后处理 conn.afterExecute(); } } }
resultSetHandler.handleResultSets处理执行的结果时会调用结果集处理器DefaultResultSetHandler#handleResultSets
public class DefaultResultSetHandler implements ResultSetHandler { @Override public ListhandleResultSets(Statement stmt) throws SQLException { ErrorContext.instance().activity("handling results").object(mappedStatement.getId()); final List multipleResults = new ArrayList<>(); int resultSetCount = 0; // 获取第一个结果集 ResultSetWrapper rsw = getFirstResultSet(stmt); // 获取结果map List resultMaps = mappedStatement.getResultMaps(); // 结果map大小 int resultMapCount = resultMaps.size(); // 校验总数 validateResultMapsCount(rsw, resultMapCount); while (rsw != null && resultMapCount > resultSetCount) { // 结果map ResultMap resultMap = resultMaps.get(resultSetCount); // 处理结果集 handleResultSet(rsw, resultMap, multipleResults, null); // 获取下一个结果集 rsw = getNextResultSet(stmt); // 清理 cleanUpAfterHandlingResultSet(); resultSetCount++; } String[] resultSets = mappedStatement.getResultSets(); if (resultSets != null) { while (rsw != null && resultSetCount < resultSets.length) { ResultMapping parentMapping = nextResultMaps.get(resultSets[resultSetCount]); if (parentMapping != null) { String nestedResultMapId = parentMapping.getNestedResultMapId(); ResultMap resultMap = configuration.getResultMap(nestedResultMapId); handleResultSet(rsw, resultMap, null, parentMapping); } rsw = getNextResultSet(stmt); cleanUpAfterHandlingResultSet(); resultSetCount++; } } return collapseSingleResultList(multipleResults); } public void handleRowValues(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException { if (resultMap.hasNestedResultMaps()) { // 嵌套结果集 ensureNoRowBounds(); checkResultHandler(); handleRowValuesForNestedResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping); } else { // 简单结果集 handleRowValuesForSimpleResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping); } } private void handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler> resultHandler, RowBounds rowBounds, ResultMapping parentMapping)throws SQLException { DefaultResultContext resultContext = new DefaultResultContext<>(); ResultSet resultSet = rsw.getResultSet(); skipRows(resultSet, rowBounds); while (shouldProcessMoreRows(resultContext, rowBounds) && !resultSet.isClosed() && resultSet.next()) { // 区分结果map ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(resultSet, resultMap, null); // 获取行值 Object rowValue = getRowValue(rsw, discriminatedResultMap, null); // 存储 storeObject(resultHandler, resultContext, rowValue, parentMapping, resultSet); } } }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)