我们知道:通过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的流程就明白了;
大体描述一下流程,如上图。