我们知道:通过XMLConfigBuild我们获取了把xml配置文件解析成的configuration对象,然后我们使用它来创建了SQLSessionFactory,这个过程封装成了一个SQLSessionFactoryBuild类;有了SQLSessionFactory我们讲究直接可以获取到SQLSession对象了;然后我们又分析了SQLSession的运行过程,它是通过映射器的注册器动态代理生成的Mapper对象,然后看了他的动态代理生成的过程,走到了这里:
private <K, V> Map<K, V> executeForMap(SqlSession sqlSession, Object[] args) {
Map<K, V> result;
Object param = method.convertArgsToSqlCommandParam(args);
if (method.hasRowBounds()) {
RowBounds rowBounds = method.extractRowBounds(args);
result = sqlSession.<K, V>selectMap(command.getName(), param, method.getMapKey(), rowBounds);
} else {
result = sqlSession.<K, V>selectMap(command.getName(), param, method.getMapKey());
}
return result;
}
那现在我们继续往下看,到底SQLSession怎么给我们执行sql语句的:
它调用了sqlSession的Map<K, V> selectMap的方法,咱们看它的实现,它的实现在DefaultSqlSession类中,
@Override
public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey) {
return this.selectMap(statement, parameter, mapKey, RowBounds.DEFAULT);
}
@Override
public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds) {
final List<? extends V> list = selectList(statement, parameter, rowBounds);
final DefaultMapResultHandler<K, V> mapResultHandler = new DefaultMapResultHandler<K, V>(mapKey,
configuration.getObjectFactory(), configuration.getObjectWrapperFactory(), configuration.getReflectorFactory());
final DefaultResultContext<V> context = new DefaultResultContext<V>();
for (V o : list) {
context.nextResultObject(o);
mapResultHandler.handleResult(context);
}
return mapResultHandler.getMappedResults();
}
继续看:
final List<? extends V> list = selectList(statement, parameter, rowBounds);
通过这个方法,我们找到了executor,源码如下:
@Override
public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
try {
MappedStatement ms = configuration.getMappedStatement(statement);
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();
}
}
executor是什么?它是执行器,是SQLSession下的四大对象之一;由它来调度另外三个对象statementHandler、ParameterHandler、ResultSetHandler等来执行sql。
那我们继续说一下其它三个对象的作用:
1)statementHandler:使数据库的Statement执行操作,它是核心,起承上启下的作用;
2)ParameterHandler:用来处理sql的参数;
3)ResultSetHandler:是执行数据的返回处理的;
那我们继续看它是怎么调度的:
return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
我们一层层进入,终于找到了org.apache.ibatis.executor.SimpleExecutor下的doQuery方法和它下面要调用的prepareStatement方法:
@Override
public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
Statement stmt = null;
try {
Configuration configuration = ms.getConfiguration();
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
stmt = prepareStatement(handler, ms.getStatementLog());
return handler.<E>query(stmt, resultHandler);
} finally {
closeStatement(stmt);
}
}
private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
Statement stmt;
Connection connection = getConnection(statementLog);
stmt = handler.prepare(connection, transaction.getTimeout());
handler.parameterize(stmt);
return stmt;
}
显然我们能够看到mybatis根据configuration来构建的StatementHandler,然后调用prepareStatement方法,对sql进行编译和参数的初始化;它的过程是:
1)首先调用了StatementHandler的prepare方法执行了预编译和基础的设置:
stmt = handler.prepare(connection, transaction.getTimeout());
2)然后通过StatementHandler的parameterize方法设置参数
handler.parameterize(stmt);
进去之后
@Override
public void parameterize(Statement statement) throws SQLException {
parameterHandler.setParameters((PreparedStatement) statement);
}
我们看到了parameterHandler进行的处理;
然后将处理好的对象再次交给StatementHandler的<E>query方法进行执行:
@Override
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
String sql = boundSql.getSql();
statement.execute(sql);
return resultSetHandler.<E>handleResultSets(statement);
}
我们接下来继续跟进:
@Override
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
return delegate.<E>query(statement, resultHandler);
}
在这里我们进入了RoutingStatementHandler,它实现了StatementHandler接口,
public class RoutingStatementHandler implements StatementHandler {
private final StatementHandler delegate;
public RoutingStatementHandler(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
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;
case CALLABLE:
delegate = new CallableStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
break;
default:
throw new ExecutorException("Unknown statement type: " + ms.getStatementType());
}
我们能够看到它创建StatementHandler对象,然后我们找到了resultSetHandler
@Override
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
PreparedStatement ps = (PreparedStatement) statement;
ps.execute();
return resultSetHandler.<E> handleResultSets(ps);
}
到这里整个SQLSession如何去处理并执行sql的流程就明白了;
大体描述一下流程,如上图。