Mybatis源码系列文章
手写源码(了解源码整体流程及重要组件)
Mybatis源码解析(一):环境搭建
Mybatis源码解析(二):全局配置文件的解析
Mybatis源码解析(三):映射配置文件的解析
Mybatis源码解析(四):sql语句及#{}、${}的解析
Mybatis源码解析(五):SqlSession会话的创建
Mybatis源码解析(六):缓存执行器操作流程
Mybatis源码解析(六):查询数据库主流程

处理流程

处理流程

@Override
public List doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {Statement stmt = null;try {// 1.获取配置实例Configuration configuration = ms.getConfiguration();// 2. new一个StatementHandler实例StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);// 3. 准备处理器,主要包括创建statement以及动态参数的设置stmt = prepareStatement(handler, ms.getStatementLog());// 4. 执行真正的数据库操作调用return handler.query(stmt, resultHandler);} finally {// 5. 关闭statementcloseStatement(stmt);}
}
进入newStatementHandler方法
public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {// 创建路由功能的StatementHandler,根据MappedStatement中的StatementTypeStatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);// 插件机制:对核心对象进行拦截statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);return statementHandler;
}
进入RoutingStatementHandler构造方法
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());}}
进入prepareStatement方法
private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {Statement stmt;// 1. 获取代理后(增加日志功能)的Connection对象Connection connection = getConnection(statementLog);// 2. 创建Statement对象(可能是一个SimpleStatement,一个PreparedStatement或CallableStatement)stmt = handler.prepare(connection, transaction.getTimeout());// 3. 参数化处理handler.parameterize(stmt);// 4. 返回执行前最后准备好的Statement对象return stmt;
}
protected Connection getConnection(Log statementLog) throws SQLException {Connection connection = transaction.getConnection();if (statementLog.isDebugEnabled()) {return ConnectionLogger.newInstance(connection, statementLog, queryStack);} else {return connection;}
}
进入transaction.getConnection方法
@Override
public Connection getConnection() throws SQLException {if (connection == null) {openConnection();}return connection;
}protected void openConnection() throws SQLException {if (log.isDebugEnabled()) {log.debug("Opening JDBC Connection");}connection = dataSource.getConnection();if (level != null) {connection.setTransactionIsolation(level.getLevel());}setDesiredAutoCommit(autoCommit);
}
通过RoutingStatementHandler handler的路由语句处理器调用prepare方法
@Override
public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException {return delegate.prepare(connection, transactionTimeout);
}
@Override
public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException {ErrorContext.instance().sql(boundSql.getSql());Statement statement = null;try {statement = instantiateStatement(connection);setStatementTimeout(statement, transactionTimeout);setFetchSize(statement);return statement;} catch (SQLException e) {closeStatement(statement);throw e;} catch (Exception e) {closeStatement(statement);throw new ExecutorException("Error preparing statement. Cause: " + e, e);}
}
进入instantiateStatement实例化Statement方法
@Override
protected Statement instantiateStatement(Connection connection) throws SQLException {String sql = boundSql.getSql();// 主键生成策略if (mappedStatement.getKeyGenerator() instanceof Jdbc3KeyGenerator) {String[] keyColumnNames = mappedStatement.getKeyColumns();if (keyColumnNames == null) {return connection.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS);} else {return connection.prepareStatement(sql, keyColumnNames);}} else if (mappedStatement.getResultSetType() == ResultSetType.DEFAULT) {return connection.prepareStatement(sql);} else {return connection.prepareStatement(sql, mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY);}
}
通过RoutingStatementHandler handler的路由语句处理器调用parameterize方法
@Override
public void parameterize(Statement statement) throws SQLException {delegate.parameterize(statement);
}
@Override
public void parameterize(Statement statement) throws SQLException {parameterHandler.setParameters((PreparedStatement) statement);
}
public class DefaultParameterHandler implements ParameterHandler {// 持有typeHandler注册器private final TypeHandlerRegistry typeHandlerRegistry;// 持有MappedStatement实例,这是一个静态的xml的一个数据库操作节点的静态信息而已private final MappedStatement mappedStatement;// 当前实际执行前的参数对象private final Object parameterObject;// 动态语言被执行后的结果sqlprivate final BoundSql boundSql;private final Configuration configuration;// 构造函数public DefaultParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {this.mappedStatement = mappedStatement;this.configuration = mappedStatement.getConfiguration();this.typeHandlerRegistry = mappedStatement.getConfiguration().getTypeHandlerRegistry();this.parameterObject = parameterObject;this.boundSql = boundSql;}@Overridepublic Object getParameterObject() {return parameterObject;}@Overridepublic void setParameters(PreparedStatement ps) {ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());// 1. 获取boundSql中的参数映射信息列表List parameterMappings = boundSql.getParameterMappings();if (parameterMappings != null) {// 1.1. 遍历参数映射列表,这个列表信息就是我们xml文件中定义的某个查询语句的所有参数映射信息,注意这个List中的参数映射元素的顺序是和真实xml中sql的参数顺序对应的for (int i = 0; i < parameterMappings.size(); i++) {ParameterMapping parameterMapping = parameterMappings.get(i);// 1.2. 只有入参类型才会设置PreparedStatementif (parameterMapping.getMode() != ParameterMode.OUT) {Object value;// 取出参数名,这里比如说是'id'String propertyName = parameterMapping.getProperty();if (boundSql.hasAdditionalParameter(propertyName)) { // issue #448 ask first for additional paramsvalue = boundSql.getAdditionalParameter(propertyName);} else if (parameterObject == null) {value = null;} else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {value = parameterObject;} else {// 1.3. 这一步的工作就是从当前实际传入的参数中获取到指定key('id')的value值,比如是'15800000000'MetaObject metaObject = configuration.newMetaObject(parameterObject);value = metaObject.getValue(propertyName);}// 2. 获取该参数对应的typeHandlerTypeHandler typeHandler = parameterMapping.getTypeHandler();// 2.1. 获取该参数对应的jdbcTypeJdbcType jdbcType = parameterMapping.getJdbcType();if (value == null && jdbcType == null) {jdbcType = configuration.getJdbcTypeForNull();}try {// 3. 重点是调用每个参数对应的typeHandler的setParameter方法为该ps设置正确的参数值typeHandler.setParameter(ps, i + 1, value, jdbcType);} catch (TypeException | SQLException e) {throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);}}}}}}
进入int类型处理器setParameter方法
public class IntegerTypeHandler extends BaseTypeHandler {@Overridepublic void setNonNullParameter(PreparedStatement ps, int i, Integer parameter, JdbcType jdbcType)throws SQLException {ps.setInt(i, parameter);}...
}
通过RoutingStatementHandler handler的路由语句处理器调用query方法
@Override
public List query(Statement statement, ResultHandler resultHandler) throws SQLException {return delegate.query(statement, resultHandler);
}
@Override
public List query(Statement statement, ResultHandler resultHandler) throws SQLException {PreparedStatement ps = (PreparedStatement) statement;ps.execute();// 结果集处理return resultSetHandler.handleResultSets(ps);
}
@Override
public List
private ResultSetWrapper getFirstResultSet(Statement stmt) throws SQLException {ResultSet rs = stmt.getResultSet();while (rs == null) {// move forward to get the first resultset in case the driver// doesn't return the resultset as the first result (HSQLDB 2.1)if (stmt.getMoreResults()) {rs = stmt.getResultSet();} else {if (stmt.getUpdateCount() == -1) {// no more results. Must be no resultsetbreak;}}}return rs != null ? new ResultSetWrapper(rs, configuration) : null;
}
private void handleResultSet(ResultSetWrapper rsw, ResultMap resultMap, List multipleResults, ResultMapping parentMapping) throws SQLException {try {if (parentMapping != null) {handleRowValues(rsw, resultMap, null, RowBounds.DEFAULT, parentMapping);} else {if (resultHandler == null) {// 实例化DefaultResultHandlerDefaultResultHandler defaultResultHandler = new DefaultResultHandler(objectFactory);// 对结果集进行映射,转换的结果存入defaultResultHandlerhandleRowValues(rsw, resultMap, defaultResultHandler, rowBounds, null);// List>multipleResults.add(defaultResultHandler.getResultList());} else {// 存储过程相关handleRowValues(rsw, resultMap, resultHandler, rowBounds, null);}}} finally {// issue #228 (close resultsets)closeResultSet(rsw.getResultSet());}
}
进入handleRowValues方法
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();// (1)根据分页信息,提取相应数据skipRows(resultSet, rowBounds);/*处理和赋值多条记录*/while (shouldProcessMoreRows(resultContext, rowBounds) && !resultSet.isClosed() && resultSet.next()) {// 通过标签的子标签对结果映射进行鉴别ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(resultSet, resultMap, null);// 将查询结果封装到POJO中Object rowValue = getRowValue(rsw, discriminatedResultMap, null);// 保存映射结果storeObject(resultHandler, resultContext, rowValue, parentMapping, resultSet);}
}
进入getRowValue
private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap, String columnPrefix) throws SQLException {// 延迟加载的映射信息final ResultLoaderMap lazyLoader = new ResultLoaderMap();// 根据resultType的值创建要映射的PO类对象Object rowValue = createResultObject(rsw, resultMap, lazyLoader, columnPrefix);if (rowValue != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) {// 获取MetaObject对象,为后面赋值做准备final MetaObject metaObject = configuration.newMetaObject(rowValue);boolean foundValues = this.useConstructorMappings;// 是否应用自动映射,也就是通过resultType进行映射if (shouldApplyAutomaticMappings(resultMap, false)) {// 根据columnName和type属性名映射赋值foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, columnPrefix) || foundValues;}// 根据我们配置ResultMap的column和property映射赋值// 如果映射存在nestedQueryId,会调用getNestedQueryMappingValue方法获取返回值foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, columnPrefix) || foundValues;foundValues = lazyLoader.size() > 0 || foundValues;rowValue = foundValues || configuration.isReturnInstanceForEmptyRow() ? rowValue : null;}return rowValue;
}
进入applyAutomaticMappings
private boolean applyAutomaticMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String columnPrefix) throws SQLException {List autoMapping = createAutomaticMappings(rsw, resultMap, metaObject, columnPrefix);boolean foundValues = false;if (!autoMapping.isEmpty()) {for (UnMappedColumnAutoMapping mapping : autoMapping) {final Object value = mapping.typeHandler.getResult(rsw.getResultSet(), mapping.column);if (value != null) {foundValues = true;}if (value != null || (configuration.isCallSettersOnNulls() && !mapping.primitive)) {// gcode issue #377, call setter on nulls (value is not 'found')metaObject.setValue(mapping.property, value);}}}return foundValues;
}
上一篇:生物学上marker是什么意思