本篇文章主要介绍mybatis查询数据库。
1、查询数据库
BaseExecutor#queryFromDatabase
public abstract class BaseExecutor implements Executor {
private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
List<E> list;
/**
* 向一级缓存里put一个占位符
*/
localCache.putObject(key, EXECUTION_PLACEHOLDER);
try {
/**
* 执行查询
*/
//SimpleExeuctor
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;
}
}
SimpleExecutor#doQuery
数据库查询流程
1、生成StatementHandler
2、? 参数赋值
3、执行查询
public class SimpleExecutor extends BaseExecutor {
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();
//1.1 生成StatementHandler
/**
* 代理StatementHandler 用你的插件去代理
* 在 StatementHandler的子类 BaseStatementHandler中 会对ParameterHandler和ResultSetHandler进行代理
*
*/
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
//1.2 ? 赋值
/**
* 1、返回一个PrepareStatement
* 2、给?设置值 #{}在mybatis启动的时候就被替换成?
*/
stmt = prepareStatement(handler, ms.getStatementLog());
//1.3 执行查询
//RoutingStatementHandler
return handler.query(stmt, resultHandler);
} finally {
closeStatement(stmt);
}
}
}
1.1 StatementHandler
mybatis四大对象之一的StatementHandler的创建流程:
1、创建RoutingStatementHandler
带有${}的sql由jdbc的Statement对象执行,带有#{}的sql对象由jdbc的PreparedStatement执行,因此RoutingStatementHandler的作用就是根据sql的类型,调用具体的Statement执行sql
2、应用插件到StatementHandler
Configuration#newStatementHandler
public class Configuration {
public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
/**
* 创建具有路由功能的StatementHandler
* 如上,RoutingStatementHandler 的构造方法会根据 MappedStatement 中的 statementType 变量创建不同的 StatementHandler 实现类。
* 默认情况下,statementType 值为 PREPARED 对应的jdbc里的PreparedStatement
*/
StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);
/**
* 代理StatementHandler 用你的插件去代理
* 应用插件到StatementHandler
*/
statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
return statementHandler;
}
}
RoutingStatementHandler
StatementHandler是mybatis对jdbc的Statement的封装,RoutingStatementHandler是对其他三个StatementHanlder的封装,只是负责上面三个StatementHandler的创建及调用。
public class RoutingStatementHandler implements StatementHandler {
//被装饰的StatementHanlder
private final StatementHandler delegate;
public RoutingStatementHandler(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
// 根据 StatementType 创建不同的 StatementHandler
switch (ms.getStatementType()) {
case STATEMENT:
//管理 Statement 对象并向数据库中推送不需要预编译的SQL语句
delegate = new SimpleStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
break;
case PREPARED:
// 管理 Statement 对象并向数据中推送需要预编译的SQL语句,
/**
* 父类构造方法中创建ParameterHandler和ResultSetHandler
*/
delegate = new PreparedStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
break;
case CALLABLE:
//管理 Statement 对象并调用数据库中的存储过程
delegate = new CallableStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
break;
default:
throw new ExecutorException("Unknown statement type: " + ms.getStatementType());
}
}
}
继续分析PreparedStatementHandler的创建流程 PreparedStatementHandler
public class PreparedStatementHandler extends BaseStatementHandler {
public PreparedStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
//父类构造器
super(executor, mappedStatement, parameter, rowBounds, resultHandler, boundSql);
}
}
BaseStatementHandler
public abstract class BaseStatementHandler implements StatementHandler {
protected BaseStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
this.configuration = mappedStatement.getConfiguration();
this.executor = executor;
this.mappedStatement = mappedStatement;
this.rowBounds = rowBounds;
this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();
this.objectFactory = configuration.getObjectFactory();
if (boundSql == null) { // issue #435, get the key before calculating the statement
generateKeys(parameterObject);
boundSql = mappedStatement.getBoundSql(parameterObject);
}
this.boundSql = boundSql;
/**
* 代理parameterHandler
*/
this.parameterHandler = configuration.newParameterHandler(mappedStatement, parameterObject, boundSql);
/**
* 代理resultSetHandler
*/
this.resultSetHandler = configuration.newResultSetHandler(executor, mappedStatement, rowBounds, parameterHandler, resultHandler, boundSql);
}
}
在BaseStatementHandler构造器内部,创建了ParameterHandler和ResultSetHandler对象。至此,mybatis四大对象均以创建完毕。至于这几个对象被称为mybatis四大对象的原因,就是只有这四个对象能被mybatis代理,即添加插件。因为Configuration在创建这几个对象时,都调用了interceptorChain.pluginAll进行代理。
1.2 ? 赋值
SimpleExecutor#prepareStatement
public class SimpleExecutor extends BaseExecutor {
private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
Statement stmt;
/**
* 获取数据库连接
*/
Connection connection = getConnection(statementLog);
//1.2.1 创建jdbc的PreparedStatment
/**
* 返回一个Statement
*/
//RoutingStatementHandler#prepare
stmt = handler.prepare(connection, transaction.getTimeout());
//1.2.2 参数赋值
/**
* 为 PreparedStatement 设置 IN 参数 : ? 赋值
*/
//RoutingStatementHandler.parameterize
handler.parameterize(stmt);
return stmt;
}
}
1.2.1 创建jdbc的PreparedStatment
RoutingStatementHandler#prepare
public class RoutingStatementHandler implements StatementHandler {
private final StatementHandler delegate;
public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException {
//BaseStatementHandler#prepare
return delegate.prepare(connection, transactionTimeout);
}
}
BaseStatementHandler#prepare
public abstract class BaseStatementHandler implements StatementHandler {
public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException {
ErrorContext.instance().sql(boundSql.getSql());
Statement statement = null;
try {
//创建jdbc的Statement
//PreparedStatementHandler#instantiateStatement
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);
}
}
}
PreparedStatementHandler#instantiateStatement
public class PreparedStatementHandler extends BaseStatementHandler {
protected Statement instantiateStatement(Connection connection) throws SQLException {
String sql = boundSql.getSql();
//调用jdbc的api创建PreparedStatement
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);
}
}
}
1.2.2 为 ? 赋值
RoutingStatementHandler.parameterize
public class RoutingStatementHandler implements StatementHandler {
public void parameterize(Statement statement) throws SQLException {
delegate.parameterize(statement);
}
}
PreparedStatementHandler#parameterize
public class PreparedStatementHandler extends BaseStatementHandler {
public void parameterize(Statement statement) throws SQLException {
/**
* 通过参数处理器 ParameterHandler 设置方法参数到 PreparedStatement 中
*/
parameterHandler.setParameters((PreparedStatement) statement);
}
}
DefaultParameterHandler#setParameters
public class DefaultParameterHandler implements ParameterHandler {
public void setParameters(PreparedStatement ps) {
ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
/**
* sql中所有的#{占位符}中的占位符 在解析Mapper文件时#{}就被替换成 ?
*/
/**
* 从 BoundSql 中获取 ParameterMapping 列表,每个 ParameterMapping
* 与原始 SQL 中的 #{xxx} 占位符一一对应
*/
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
if (parameterMappings != null) {
for (int i = 0; i < parameterMappings.size(); i++) {
ParameterMapping parameterMapping = parameterMappings.get(i);
// 检测参数类型,排除掉 mode 为 OUT 类型的 parameterMapping
if (parameterMapping.getMode() != ParameterMode.OUT) {
Object value;
//获取属性名
String propertyName = parameterMapping.getProperty();
if (boundSql.hasAdditionalParameter(propertyName)) { // issue #448 ask first for additional params
//检测 BoundSql 的 additionalParameters 是否包含 propertyName
value = boundSql.getAdditionalParameter(propertyName);
} else if (parameterObject == null) {
value = null;
// 检测运行时参数是否有相应的类型解析器
} else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
/**
* 若运行时参数的类型有相应的类型处理器 TypeHandler,则将
* parameterObject 设为当前属性的值。
*/
value = parameterObject;
} else {
//为用户传入的参数 parameterObject 创建元信息对象
MetaObject metaObject = configuration.newMetaObject(parameterObject);
//从用户传入的参数中获取 propertyName 对应的值
value = metaObject.getValue(propertyName);
}
//以上为获取 #{xxx} 占位符属性所对应的运行时参数
//*************************************************
// 分割线以下的代码则是获取 #{xxx} 占位符属性对应的 TypeHandler,并在最后通过 TypeHandler 将运行时参数值设置到 PreparedStatement 中
TypeHandler typeHandler = parameterMapping.getTypeHandler();
JdbcType jdbcType = parameterMapping.getJdbcType();
if (value == null && jdbcType == null) {
// 此处 jdbcType = JdbcType.OTHER
jdbcType = configuration.getJdbcTypeForNull();
}
try {
//BaseTypeHandler
//由类型处理器 typeHandler 向 ParameterHandler 设置参数
typeHandler.setParameter(ps, i + 1, value, jdbcType);
} catch (TypeException e) {
throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);
} catch (SQLException e) {
throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);
}
}
}
}
}
}
1.3 执行查询
RoutingStatementHandler#query
public class RoutingStatementHandler implements StatementHandler {
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
//PreparedStatement
return delegate.<E>query(statement, resultHandler);
}
}
PreparedStatementHandler#query
调用jdbc原生api查询数据库,然后处理返回的结果集
public class PreparedStatementHandler extends BaseStatementHandler {
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
PreparedStatement ps = (PreparedStatement) statement;
/**
* 执行查询 这是jdbc原生PreparedStatement的方法
*/
ps.execute();
/**
* 处理返回结果集
*/
return resultSetHandler.handleResultSets(ps);
}
}
DefaultResultSetHandler.handleResultSets
结果集处理这块还是优点复杂的,感兴趣的同学可以深入了解下。
public class DefaultResultSetHandler implements ResultSetHandler {
public List<Object> handleResultSets(Statement stmt) throws SQLException {
ErrorContext.instance().activity("handling results").object(mappedStatement.getId());
// 要返回的结果
final List<Object> multipleResults = new ArrayList<>();
// 迭代变量,结果集的个数
int resultSetCount = 0;
// 获取第一个结果集,并包装成ResultSetWrapper对象,
// ResultSetWrapper对象含有已映射和未映射的列名和属性的对应关系
ResultSetWrapper rsw = getFirstResultSet(stmt);
// 获取所有的ResultMap
List<ResultMap> resultMaps = mappedStatement.getResultMaps();
// ResultMap的个数
int resultMapCount = resultMaps.size();
// 校验:如果结果集有数据,但是没有定义返回的结果类型,就会报错
validateResultMapsCount(rsw, resultMapCount);
while (rsw != null && resultMapCount > resultSetCount) {
// 依次获取ResultMap
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);
}
private ResultSetWrapper getFirstResultSet(Statement stmt) throws SQLException {
/**
* 获取结果集
*/
ResultSet rs = stmt.getResultSet();
while (rs == null) {
/**
* 移动 ResultSet 指针到下一个上,有些数据库驱动可能需要使用者先调用 getMoreResults 方法,然后才能调用 getResultSet 方法
* 获取到第一个 ResultSet
*/
// 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 resultset
break;
}
}
}
/**
* 将ResultSet封装到 ResultSetWrapper 中。
* ResultSetWrapper 中包含了 ResultSet 一些元信息,比如列名称、每列对应的 JdbcType、
* 以及每列对应的 Java 类名(class name,譬如 java.lang.String)等。
*/
return rs != null ? new ResultSetWrapper(rs, configuration) : null;
}
private void handleResultSet(ResultSetWrapper rsw, ResultMap resultMap, List<Object> multipleResults, ResultMapping parentMapping) throws SQLException {
try {
if (parentMapping != null) {
//多结果集相关逻辑,不分析了
handleRowValues(rsw, resultMap, null, RowBounds.DEFAULT, parentMapping);
} else {
if (resultHandler == null) {
// 如果结果处理器为空,则使用默认的结果处理器,没有自定义的情况下,都是走这个流程
DefaultResultHandler defaultResultHandler = new DefaultResultHandler(objectFactory);
// 处理每一行的值
handleRowValues(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());
}
}
public void handleRowValues(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {
// 如果有嵌套的ResultMap
if (resultMap.hasNestedResultMaps()) {
ensureNoRowBounds();
checkResultHandler();
// 处理含有嵌套ResultMap的结果
handleRowValuesForNestedResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
} else {
// 处理不含有嵌套ResultMap的结果
handleRowValuesForSimpleResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
}
}
private void handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping)
throws SQLException {
DefaultResultContext<Object> resultContext = new DefaultResultContext<>();
ResultSet resultSet = rsw.getResultSet();
// 跳过已处理的行
skipRows(resultSet, rowBounds);
while (shouldProcessMoreRows(resultContext, rowBounds) && !resultSet.isClosed() && resultSet.next()) {
ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(resultSet, resultMap, null);
//获取行值
Object rowValue = getRowValue(rsw, discriminatedResultMap, null);
storeObject(resultHandler, resultContext, rowValue, parentMapping, resultSet);
}
}
private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap, String columnPrefix) throws SQLException {
final ResultLoaderMap lazyLoader = new ResultLoaderMap();
// 创建结果对象
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;
// 是否使用自动映射
if (shouldApplyAutomaticMappings(resultMap, false)) {
foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, columnPrefix) || foundValues;
}
// 给对象的属性赋值
foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, columnPrefix) || foundValues;
foundValues = lazyLoader.size() > 0 || foundValues;
rowValue = foundValues || configuration.isReturnInstanceForEmptyRow() ? rowValue : null;
}
return rowValue;
}
private boolean applyPropertyMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, ResultLoaderMap lazyLoader, String columnPrefix)
throws SQLException {
// 已经映射的列名集合
final List<String> mappedColumnNames = rsw.getMappedColumnNames(resultMap, columnPrefix);
boolean foundValues = false;
// 所有属性和列的映射规则
final List<ResultMapping> propertyMappings = resultMap.getPropertyResultMappings();
for (ResultMapping propertyMapping : propertyMappings) {
//列名
String column = prependPrefix(propertyMapping.getColumn(), columnPrefix);
if (propertyMapping.getNestedResultMapId() != null) {
// the user added a column attribute to a nested result map, ignore it
column = null;
}
if (propertyMapping.isCompositeResult()
|| (column != null && mappedColumnNames.contains(column.toUpperCase(Locale.ENGLISH)))
|| propertyMapping.getResultSet() != null) {
// 根据列名,获取属性值
Object value = getPropertyMappingValue(rsw.getResultSet(), metaObject, propertyMapping, lazyLoader, columnPrefix);
// issue #541 make property optional
//属性名
final String property = propertyMapping.getProperty();
if (property == null) {
continue;
} else if (value == DEFERRED) {
foundValues = true;
continue;
}
if (value != null) {
foundValues = true;
}
if (value != null || (configuration.isCallSettersOnNulls() && !metaObject.getSetterType(property).isPrimitive())) {
// gcode issue #377, call setter on nulls (value is not 'found')
//给对象的属性赋值
metaObject.setValue(property, value);
}
}
}
return foundValues;
}
private Object getPropertyMappingValue(ResultSet rs, MetaObject metaResultObject, ResultMapping propertyMapping, ResultLoaderMap lazyLoader, String columnPrefix)
throws SQLException {
//嵌入查询
if (propertyMapping.getNestedQueryId() != null) {
return getNestedQueryMappingValue(rs, metaResultObject, propertyMapping, lazyLoader, columnPrefix);
} else if (propertyMapping.getResultSet() != null) {
addPendingChildRelation(rs, metaResultObject, propertyMapping); // TODO is that OK?
return DEFERRED;
} else {
//获取属性的类型处理器
final TypeHandler<?> typeHandler = propertyMapping.getTypeHandler();
final String column = prependPrefix(propertyMapping.getColumn(), columnPrefix);
//类型处理器
return typeHandler.getResult(rs, column);
}
}
}