DemoController->test():
// ThreadLocal存储page对象,参考插件探究
PageHelper.startPage(1, 10);
QueryWrapper queryWrapper = new QueryWrapper<>();
queryWrapper.eq("id", 1);
queryWrapper.eq("pid", 2);
service.list(queryWrapper);
ServiceImpl->list():
// 底层调用mapper方法
return baseMapper.selectList(queryWrapper);
MybatisMapperProxy->invoke():
// MybatisMapperMethod记录sql的类型、语句类型、参数等信息,参考参数值设置探究
final MybatisMapperMethod mapperMethod = cachedMapperMethod(method);
return mapperMethod.execute(sqlSession, args);
MybatisMapperMethod->execute():
// 根据返回值的不同选择不同的方法
else if (method.returnsMany()) {
result = executeForMany(sqlSession, args);
}
MybatisMapperMethod->executeForMany():
// param要么是map类型,要么返回第一个参数
Object param = method.convertArgsToSqlCommandParam(args);
......
result = sqlSession.selectList(command.getName(), param);
SqlSessionTemplate->selectList():
// sqlSessionProxy是一个代理类,参考启动阶段探究
return this.sqlSessionProxy.selectList(statement, parameter);
SqlSessionTemplate->SqlSessionInterceptor->invoke():
// 每次查询都是一个defaultSqlSession
SqlSession sqlSession = getSqlSession(
SqlSessionTemplate.this.sqlSessionFactory,
SqlSessionTemplate.this.executorType,
SqlSessionTemplate.this.exceptionTranslator);
try {
// 下面这条语句执行的是defaultSqlSession的selectList方法
Object result = method.invoke(sqlSession, args);
}
......
// 释放连接,参考数据库连接池
finally {
if (sqlSession != null) {
closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
}
}
DefaultSqlSession->selectList():
return this.selectList(statement, parameter, RowBounds.DEFAULT);
DefaultSqlSession->selectList():
MappedStatement ms = configuration.getMappedStatement(statement);
return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
Plugin->invoke():
// signatureMap的key是拦截器接口反射类,value是拦截的方法
// 如果拦截的类和方法全都符合的话,就走拦截器的拦截方法
Set methods = signatureMap.get(method.getDeclaringClass());
if (methods != null && methods.contains(method)) {
return interceptor.intercept(new Invocation(target, method, args));
}
// 否则走原来的方法,比如分页器拦截update方法时,就会走此
return method.invoke(target, args);
// invocation,包含被代理类,被代理方法,方法参数信息
// 这一段的详细解释参考插件探究
PageInterceptor->intercept():
......
// 根据sql源返回绑定sql对象,参考启动后动态SQL拼接探究
boundSql = ms.getBoundSql(parameter);
......
Long count = count(executor, ms, parameter, rowBounds, resultHandler, boundSql); // --1
// 最终执行的是baseEcecutor的方法
BaseExecutor->query(): // --1
list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
BaseExecutor->queryFromDatabase():
list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
MybatisSimpleExecutor->doQuery():
try {
Configuration configuration = ms.getConfiguration();
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql); // --2
// 底层最终调用con.prepareStatement(sql);ps.setString(1, "2");
stmt = prepareStatement(handler, ms.getStatementLog(), false); // --4
return stmt == null ? Collections.emptyList() : handler.query(stmt, resultHandler);
} finally {
// 底层调用ps.close()
closeStatement(stmt);
}
RoutingStatementHandler->query():
return delegate.query(statement, resultHandler);
PreparedStatementHandler->query():
// 底层最终调用ps.executeQuery()方法
ps.execute();
// 可以看到传过来的resultHandler似乎并没有什么用
// 使用结果集处理,返回list对象,执行rs.close(),这一段的详细过程参考ORM探究
return resultSetHandler.handleResultSets(ps);
Configuration->newStatementHandler(): // --2
// 实例化语句处理器,会包含参数处理器与结果集处理器
StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql); // --3
// 拦截器链有拦截语句处理器(PerformanceInterceptor),所以返回Plugin类
statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
return statementHandler;
RoutingStatementHandler->RoutingStatementHandler(): // --3
// 因为语句类型是预编译(带有?),所以实例化PreparedStatementHandler
switch (ms.getStatementType()) {
case STATEMENT:
delegate = new SimpleStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
break;
case PREPARED:
delegate = new PreparedStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
break;
PreparedStatementHandler->BaseStatementHandler():
// 调用的是父类的构造方法
super(executor, mappedStatement, parameter, rowBounds, resultHandler, boundSql);
BaseStatementHandler->BaseStatementHandler():
/*实例化参数处理器,这边会根据拦截器链来看是否需要动态代理
Configuration->newParameterHandler():ParameterHandler parameterHandler = mappedStatement.getLang().createParameterHandler(mappedStatement, parameterObject, boundSql);
MybatisXMLLanguageDriver->createParameterHandler():return new MybatisDefaultParameterHandler(mappedStatement, parameterObject, boundSql);
// processBatch包含了一段填充主键的过程,这边参考插入时主键策略探究
MybatisDefaultParameterHandler->MybatisDefaultParameterHandler():super(mappedStatement, processBatch(mappedStatement, parameterObject), boundSql);
*/
this.parameterHandler = configuration.newParameterHandler(mappedStatement, parameterObject, boundSql);
// 实例化结果集处理器,这边会根据拦截器链来看是否需要动态代理
this.resultSetHandler = configuration.newResultSetHandler(executor, mappedStatement, rowBounds, parameterHandler, resultHandler, boundSql);
MybatisSimpleExecutor->prepareStatement() // --4
// 从数据库连接池中获取一个连接
Connection connection = getConnection(statementLog);
// 设定了staticSql,参考JDBC探究与最终拼接SQL探究
stmt = handler.prepare(connection, transaction.getTimeout());
if (stmt == null && !isCursor) {
return null;
} else {
// 设定了bindValues,参考JDBC探究与最终拼接SQL探究
handler.parameterize(stmt);
return stmt;
}