Mybatis 执行流程深入浅出
本文继上篇mybatis
初始化流程后,剖析其执行流程
还是这几个灵魂问题:
- Mybatis解决了什么问题? 无非是简化数据库操作、实现封装、让程序员更关注SQL本身、维护便利
- 它是如何解决这些问题的?
- Mybatis是运行在什么样的环境下的?
- 它如何读取解析用户定义的配置信息?即如何初始化的
- 它的环境结构是什么样的?
- 在这一环境下如何 实现做增删查改
- 如何执行SQL
- 如何执行动态SQL
- 如何拼接查询参数等等
上篇文章解答了 2问的 1、2、3小问,这篇文章就来说说剩下的几个问题
也是大家使用得最多、最关心的问题
正经的分割线
先给出一张图,帮助大家能快速了解流程
同样,这里搬出我们上篇文章的TestCase
注意 阅读
序号 (1)、(2)、(3)、(4)、(5)、(6)...
Test.java
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(“xxx/mybatis.xml”);
// 使用一个SqlSession作为此次连接, 主要讲这儿,初始化流程
SqlSession sqlSession = sqlSessionFactory.openSession();
(1)动态代理获取代理的mapper对象
CustomMapper mapper = sqlSession.getMapper(DemoMapper.class);
Map<String,Object> map = new HashMap<>();
map.put("id","1");
(4) 执行代理对象的方法
System.out.println(mapper.select(map));
sqlSession.close();
获取动态代理的mapper
DefaultSqlSession
(2)通过默认的sqlsession获取到上篇文章讲到的configuration(存储着mappers)
@Override
public <T> T getMapper(Class<T> type) {
// 从
return configuration.getMapper(type, this);
}
MapperRegistry
(2)从knownMappers中拿到 代理工厂,使用工厂生成代理对象
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
if (mapperProxyFactory == null) {
throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
}
try {
return mapperProxyFactory.newInstance(sqlSession);
} catch (Exception e) {
throw new BindingException("Error getting mapper instance. Cause: " + e, e);
}
}
这里贴上关键点:本质是通过Proxy.newProxyInstance 来生成的代理对象
MapperRegistry
(3)本质是通过MapperProxyFactory
public class MapperProxyFactory<T> {
private final Class<T> mapperInterface;
private final Map<Method, MapperMethod> methodCache = new ConcurrentHashMap<>();
public MapperProxyFactory(Class<T> mapperInterface) {
this.mapperInterface = mapperInterface;
}
public Class<T> getMapperInterface() {
return mapperInterface;
}
public Map<Method, MapperMethod> getMethodCache() {
return methodCache;
}
@SuppressWarnings("unchecked")
protected T newInstance(MapperProxy<T> mapperProxy) {
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
}
public T newInstance(SqlSession sqlSession) {
// 这里的 MapperProxy<T> implements InvocationHandler 借助了InvocationHandler,实现invoke 方法,进而实现代理对象调用逻辑控制
具体调用请回到上面TestCase中的 (4)
final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);
return newInstance(mapperProxy);
}
}
执行代理对象的方法
MapperProxy
(5)执行具体方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
if (Object.class.equals(method.getDeclaringClass())) {
//如果是object类的默认方法,比如equals,hashcode什么的
return method.invoke(this, args);
} else if (method.isDefault()) {
//如果是default方法,java8,9处理不同。但都是把方法绑定到代理对象再调用
if (privateLookupInMethod == null) {
return invokeDefaultMethodJava8(proxy, method, args);
} else {
return invokeDefaultMethodJava9(proxy, method, args);
}
}
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
// 重点来了
(6)获取mapper执行的方法
final MapperMethod mapperMethod = cachedMapperMethod(method);
(8)真正执行传进来的mapper操作
return mapperMethod.execute(sqlSession, args);
}
(7)看是否有缓存,如果没有就创建新的 mapper的执行方法
private MapperMethod cachedMapperMethod(Method method) {
return methodCache.computeIfAbsent(method,
k -> new MapperMethod(mapperInterface, method, sqlSession.getConfiguration()));
}
MapperMethod
public class MapperMethod {
private final SqlCommand command;
private final MethodSignature method;
public MapperMethod(Class<?> mapperInterface, Method method, Configuration config) {
// SQL的信息,select|insert|xxx,初始化的MappedStatement等信息
this.command = new SqlCommand(config, mapperInterface, method);
// 当前执行方法签名,包含返回类型、resultHanlder、行范围、查询参数映射解析等信息
this.method = new MethodSignature(config, mapperInterface, method);
}
(8)执行sql
public Object execute(SqlSession sqlSession, Object[] args) {
Object result;
switch (command.getType()) {
case INSERT: {
// 如果是CUD操作,将传入的参数,映射到具体某个位置的SQL参数上
// CUD操作其实都是调用的 update方法, 详见(9)
// 下面先讲这个流程,select在之后讲
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.insert(command.getName(), param));
break;
}
case UPDATE: {
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.update(command.getName(), param));
break;
}
case DELETE: {
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.delete(command.getName(), param));
break;
}
case SELECT:
if (method.returnsVoid() && method.hasResultHandler()) {
executeWithResultHandler(sqlSession, args);
result = null;
} else if (method.returnsMany()) {
result = executeForMany(sqlSession, args);
} else if (method.returnsMap()) {
result = executeForMap(sqlSession, args);
} else if (method.returnsCursor()) {
result = executeForCursor(sqlSession, args);
} else {
Object param = method.convertArgsToSqlCommandParam(args);
result = sqlSession.selectOne(command.getName(), param);
if (method.returnsOptional()
&& (result == null || !method.getReturnType().equals(result.getClass()))) {
result = Optional.ofNullable(result);
}
}
break;
case FLUSH:
result = sqlSession.flushStatements();
break;
default:
throw new BindingException("Unknown execution method for: " + command.getName());
}
if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) {
throw new BindingException("Mapper method '" + command.getName()
+ " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ").");
}
return result;
}
······
}
增删改 的流程
DefaultSqlSession
······
@Override
public int update(String statement, Object parameter) {
try {
(9)获取MappedStatement,通过执行器执行
dirty = true;
MappedStatement ms = configuration.getMappedStatement(statement);
return executor.update(ms, wrapCollection(parameter));
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error updating database. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
······
SimpleExecutor
@Override
public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
Statement stmt = null;
try {
Configuration configuration = ms.getConfiguration();
// 创建一个statement的处理器
(10)
StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null);
(11)
stmt = prepareStatement(handler, ms.getStatementLog());
return handler.update(stmt);
} finally {
closeStatement(stmt);
}
}
(11)这里就是jdbc熟悉的,获取连接,准备Statement,设置参数到Statement
private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
Statement stmt;
Connection connection = getConnection(statementLog);
stmt = handler.prepare(connection, transaction.getTimeout());
// parameterHandler设置参数
handler.parameterize(stmt);
return stmt;
}
Configuration
(10)
public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);
// 将StatementHandler加入调用链里,返回代理的statementHandler, 供插件用, 分页插件可通过这儿来拦截执行
statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
return statementHandler;
}
DefaultParameterHandler
public class DefaultParameterHandler implements ParameterHandler {
private final TypeHandlerRegistry typeHandlerRegistry;
private final MappedStatement mappedStatement;
private final Object parameterObject;
private 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;
}
@Override
public Object getParameterObject() {
return parameterObject;
}
(12)设置PreparedStatement 参数的逻辑
@Override
public void setParameters(PreparedStatement ps) {
ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
// 获取到xml中配置的 参数
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
if (parameterMappings != null) {
for (int i = 0; i < parameterMappings.size(); i++) {
ParameterMapping parameterMapping = parameterMappings.get(i);
if (parameterMapping.getMode() != ParameterMode.OUT) {
Object value;
// 拿到名称
String propertyName = parameterMapping.getProperty();
// 首先看是否给参数设置了“额外”的名称,如果是直接赋值
if (boundSql.hasAdditionalParameter(propertyName)) { // issue #448 ask first for additional params
value = boundSql.getAdditionalParameter(propertyName);
} else if (parameterObject == null) {
value = null;
// 使用mybatis内置的java常用类型的type映射
} else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
value = parameterObject;
} else {
// 否则尝试从元数据中尝试获取 值
MetaObject metaObject = configuration.newMetaObject(parameterObject);
value = metaObject.getValue(propertyName);
}
TypeHandler typeHandler = parameterMapping.getTypeHandler();
JdbcType jdbcType = parameterMapping.getJdbcType();
if (value == null && jdbcType == null) {
// 都为空则,通过null获取type
jdbcType = configuration.getJdbcTypeForNull();
}
try {
// 设置对应参数 -- 底层PreparedStatement.setxxx(i + 1, value)
typeHandler.setParameter(ps, i + 1, value, jdbcType);
} catch (TypeException | SQLException e) {
throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);
}
}
}
}
}
}
PreparedStatementHandler
(13)给statement设置好参数后,到通过PreparedStatementHandler真正执行update的时候了
@Override
public int update(Statement statement) throws SQLException {
PreparedStatement ps = (PreparedStatement) statement;
ps.execute();
// 获取affectRows数量
int rows = ps.getUpdateCount();
Object parameterObject = boundSql.getParameterObject();
// 主键返回后的执行策略,比如处理数据库自增主键
KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();
keyGenerator.processAfter(executor, mappedStatement, ps, parameterObject);
return rows;
}
到此增删改操作流程全部结束
下面开始讲Select执行流程
和上述相同部分会一笔带过,主要差异在结果集的映射上
这里 阅读
序号重排 从mapper.select(map) 上的(4)开始,(5)、(6)...
MapperMethod
(5)接着从MapperMethod开始
case SELECT:
if (method.returnsVoid() && method.hasResultHandler()) {
// 如果无返回值,有结果集处理器
executeWithResultHandler(sqlSession, args);
result = null;
} else if (method.returnsMany()) {
// 如果返回list
result = executeForMany(sqlSession, args);
} else if (method.returnsMap()) {
// 如果返回map
result = executeForMap(sqlSession, args);
} else if (method.returnsCursor()) {
// 查询下标
result = executeForCursor(sqlSession, args);
} else {
// 如果单个结果
Object param = method.convertArgsToSqlCommandParam(args);
result = sqlSession.selectOne(command.getName(), param);
if (method.returnsOptional()
&& (result == null || !method.getReturnType().equals(result.getClass()))) {
result = Optional.ofNullable(result);
}
}
break;
private <E> Object executeForMany(SqlSession sqlSession, Object[] args) {
List<E> result;
(6)如果是多个则转换成参数为map映射,单个则直接是当前参数,没有则为null
Object param = method.convertArgsToSqlCommandParam(args);
// 默认分页,rowBounds 基于内存实现分页,不建议使用
if (method.hasRowBounds()) {
RowBounds rowBounds = method.extractRowBounds(args);
result = sqlSession.selectList(command.getName(), param, rowBounds);
} else {
// 执行查询 详见(9)
result = sqlSession.selectList(command.getName(), param);
}
// issue #510 Collections & arrays support
if (!method.getReturnType().isAssignableFrom(result.getClass())) {
if (method.getReturnType().isArray()) {
return convertToArray(result);
} else {
return convertToDeclaredCollection(sqlSession.getConfiguration(), result);
}
}
return result;
}
(7)通过解析器解析参数,构造参数映射
public Object convertArgsToSqlCommandParam(Object[] args) {
return paramNameResolver.getNamedParams(args);
}
ParamNameResolver
(8)解析names映射的地方,在mapper方法上添加了 @Param 注解,会解析到names里
public ParamNameResolver(Configuration config, Method method) {
final Class<?>[] paramTypes = method.getParameterTypes();
final Annotation[][] paramAnnotations = method.getParameterAnnotations();
final SortedMap<Integer, String> map = new TreeMap<>();
int paramCount = paramAnnotations.length;
// get names from @Param annotations
for (int paramIndex = 0; paramIndex < paramCount; paramIndex++) {
if (isSpecialParameter(paramTypes[paramIndex])) {
// skip special parameters
continue;
}
String name = null;
for (Annotation annotation : paramAnnotations[paramIndex]) {
if (annotation instanceof Param) {
hasParamAnnotation = true;
name = ((Param) annotation).value();
break;
}
}
if (name == null) {
// @Param was not specified.
//Spring MVC 底层调用的不是JDK的API Spring MVC底层是去解析字节码
//在jdk8以前 调用这个getName 会有问题 arg0
//jdk8
if (config.isUseActualParamName()) {
name = getActualParamName(method, paramIndex);
}
if (name == null) {
// use the parameter index as the name ("0", "1", ...)
// gcode issue #71
name = String.valueOf(map.size());
}
}
map.put(paramIndex, name);
}
names = Collections.unmodifiableSortedMap(map);
}
public Object getNamedParams(Object[] args) {
final int paramCount = names.size();
if (args == null || paramCount == 0) {
return null;
} else if (!hasParamAnnotation && paramCount == 1) {
return args[names.firstKey()];
} else {
final Map<String, Object> param = new ParamMap<>();
int i = 0;
for (Map.Entry<Integer, String> entry : names.entrySet()) {
//names : arg0,arg1
param.put(entry.getValue(), args[entry.getKey()]);
// add generic param names (param1, param2, ...)
final String genericParamName = GENERIC_NAME_PREFIX + String.valueOf(i + 1);
// ensure not to overwrite parameter named with @Param
if (!names.containsValue(genericParamName)) {
param.put(genericParamName, args[entry.getKey()]);
}
i++;
}
return param;
}
}
DefaultSqlSession
(9)
@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();
}
}
BaseExecutor
(10)
@Override
public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
BoundSql boundSql = ms.getBoundSql(parameter);
(11)获取缓存的key
CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);
(12)
return query(ms, parameter, rowBounds, resultHandler, key, boundSql);
}
@Override
public CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql) {
if (closed) {
throw new ExecutorException("Executor was closed.");
}
CacheKey cacheKey = new CacheKey();
// 根据SQL的id(com.DemoMapper.select),开启分页的查询范围(起始位置,查询条数),SQL语句,从方法上传过来的参数,返回的结果value值
// 五个条件来判断,是否是相同的查询,做缓存key
cacheKey.update(ms.getId());
cacheKey.update(rowBounds.getOffset());
cacheKey.update(rowBounds.getLimit());
cacheKey.update(boundSql.getSql());
// 获取到xml中配置的 参数
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
TypeHandlerRegistry typeHandlerRegistry = ms.getConfiguration().getTypeHandlerRegistry();
// mimic DefaultParameterHandler logic
// 这里与上面做CUD操作时的 (12)DefaultParameterHandler设置PreparedStatement参数的逻辑 相同,不再赘述
for (ParameterMapping parameterMapping : parameterMappings) {
if (parameterMapping.getMode() != ParameterMode.OUT) {
Object value;
String propertyName = parameterMapping.getProperty();
if (boundSql.hasAdditionalParameter(propertyName)) {
value = boundSql.getAdditionalParameter(propertyName);
} else if (parameterObject == null) {
value = null;
} else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
value = parameterObject;
} else {
MetaObject metaObject = configuration.newMetaObject(parameterObject);
value = metaObject.getValue(propertyName);
}
// 通过获取到的value更新 缓存key
cacheKey.update(value);
}
}
if (configuration.getEnvironment() != null) {
// issue #176
cacheKey.update(configuration.getEnvironment().getId());
}
return cacheKey;
}
// CacheKey类 中代码计算hashcode
public void update(Object object) {
// 如果为空则为1,不为空判断是否是数组,不是直接返回对象hashcode,是则判断具体是哪一种类型数组,进行hash运算
int baseHashCode = object == null ? 1 : ArrayUtil.hashCode(object);
//每update一次累加一次
count++;
checksum += baseHashCode;
baseHashCode *= count;
hashcode = multiplier * hashcode + baseHashCode;
updateList.add(object);
}
(12)执行查询
@Override
public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());
if (closed) {
throw new ExecutorException("Executor was closed.");
}
// 如果当前没有经历过查询,并且需要更新缓存
if (queryStack == 0 && ms.isFlushCacheRequired()) {
clearLocalCache();
}
List<E> list;
try {
queryStack++;
list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;
if (list != null) {
//对于数据库的存储过程进行输出资源处理
handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
} else {
(13)查询
list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
}
} finally {
queryStack--;
}
if (queryStack == 0) {
for (DeferredLoad deferredLoad : deferredLoads) {
deferredLoad.load();
}
// issue #601
deferredLoads.clear();
if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
// issue #482
clearLocalCache();
}
}
return list;
}
private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
List<E> list;
// 占位符
localCache.putObject(key, EXECUTION_PLACEHOLDER);
try {
(13)
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
(13)和上面CUD 相同的逻辑
@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());
(14)
return handler.query(stmt, resultHandler);
} finally {
closeStatement(stmt);
}
}
PreparedStatementHandler
(14)
@Override
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
PreparedStatement ps = (PreparedStatement) statement;
ps.execute();
(15)处理结果集
return resultSetHandler.handleResultSets(ps);
}
DefaultResultSetHandler
(15)
@Override
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;
// 有多个结果集取第一个,将ps取得的结果集 - ResultSet 包装在 wrapper中,其中还包含configuration信息
ResultSetWrapper rsw = getFirstResultSet(stmt);
List<ResultMap> resultMaps = mappedStatement.getResultMaps();
int resultMapCount = resultMaps.size();
validateResultMapsCount(rsw, resultMapCount);
// 遍历所有结果集
while (rsw != null && resultMapCount > resultSetCount) {
ResultMap resultMap = resultMaps.get(resultSetCount);
(16)处理单个结果集
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);
}
(16)
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);
multipleResults.add(defaultResultHandler.getResultList());
} else {
(17)处理具体一行的结果值
handleRowValues(rsw, resultMap, resultHandler, rowBounds, null);
}
}
} finally {
// issue #228 (close resultsets)
closeResultSet(rsw.getResultSet());
}
}
(17)
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);
}
}
(18)
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);
// 遍历resultSet
while (shouldProcessMoreRows(resultContext, rowBounds) && !resultSet.isClosed() && resultSet.next()) {
// 解析鉴别器,<discriminator>标签 - 用于 当某个字段满足一定条件时,使用指定的resultMap。比如
// <discriminator column="enabled" javaType="int">
// <case value="1" resultMap="testMap1"/>
// <case value="0" resultMap="testMap2"/>
// </discriminator>
ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(resultSet, resultMap, null);
(19)取值
Object rowValue = getRowValue(rsw, discriminatedResultMap, null);
// 将取出来的值,放入context中,再将context的值存入resultHandler
storeObject(resultHandler, resultContext, rowValue, parentMapping, resultSet);
}
}
(19)
private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap, String columnPrefix) throws SQLException {
// 当需要进行循环结果集映射时,使用到的懒加载 LoadPair
final ResultLoaderMap lazyLoader = new ResultLoaderMap();
// 创建空map存储值
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;
// 是否自动映射 通过resultMap 的 automapping属性设置, 默认启用
if (shouldApplyAutomaticMappings(resultMap, false)) {
foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, columnPrefix) || foundValues;
}
// 自定义的映射 比如 通过resultMap 的 子标签<id>、<result>设置
foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, columnPrefix) || foundValues;
foundValues = lazyLoader.size() > 0 || foundValues;
rowValue = foundValues || configuration.isReturnInstanceForEmptyRow() ? rowValue : null;
}
return rowValue;
}
// 到这里查询就结束了,后面就是上面的流程,关闭ps等资源,然后将结果放入缓存等。