MapperScannerConfigurer
org.mybatis.spring.mapper.MapperScannerConfigurer#postProcessBeanDefinitionRegistry
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
if (this.processPropertyPlaceHolders) {
processPropertyPlaceHolders();
}
ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
scanner.setAddToConfig(this.addToConfig);
//指定扫描的注解
scanner.setAnnotationClass(this.annotationClass);
//指定扫描的接口
scanner.setMarkerInterface(this.markerInterface);
scanner.setSqlSessionFactory(this.sqlSessionFactory);
scanner.setSqlSessionTemplate(this.sqlSessionTemplate);
scanner.setSqlSessionFactoryBeanName(this.sqlSessionFactoryBeanName);
scanner.setSqlSessionTemplateBeanName(this.sqlSessionTemplateBeanName);
scanner.setResourceLoader(this.applicationContext);
scanner.setBeanNameGenerator(this.nameGenerator);
//指定的注解进行注册
scanner.registerFilters();
// 解析配置的mapper接口包
scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage,
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS));
}
org.mybatis.spring.mapper.ClassPathMapperScanner#doScan
//将包下的class变为 beanDefinitions
Set<BeanDefinitionHolder> beanDefinitions =
//调用 ClassPathBeanDefinitionScanner#doScan
super.doScan(basePackages);
//查看该方法
processBeanDefinitions(beanDefinitions);
查看
org.mybatis.spring.mapper.ClassPathMapperScanner#processBeanDefinitions
//对 BeanDefinition 的属性进行填充值
for (BeanDefinitionHolder holder : beanDefinitions) {
definition = (GenericBeanDefinition) holder.getBeanDefinition();
definition.getConstructorArgumentValues()
.addGenericArgumentValue(definition.getBeanClassName()); // issue #59
// 注册了 mapperFactoryBean class,这个是 Mapper 接口代理实例的入口类
// mapperFactoryBean 中的 MapperFactoryBean#getObject 方法用于生成mapper的代理类
definition.setBeanClass(this.mapperFactoryBean.getClass());
// 注册了 sqlSessionFactory
if (StringUtils.hasText(this.sqlSessionFactoryBeanName)) {
definition.getPropertyValues().add("sqlSessionFactory",
new RuntimeBeanReference(this.sqlSessionFactoryBeanName));
explicitFactoryUsed = true;
}
}
注意
@Autowired
在注入 UserMapper 实例时,会将 MapperFactoryBean#getObject 方法返回的实例注入
@Autowired
private UserMapper userMapper;
上面注册了MapperFactoryBean类,查看该类
查看父类,发现 org.mybatis.spring.support.SqlSessionDaoSupport
// 会调用该方法,将配置的 sqlSessionFactory 对象传入进来
public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
if (!this.externalSqlSession) {
// sqlSession 是 mybatis 的顶层接口,于数据库交换的对象,查看该类
this.sqlSession = new SqlSessionTemplate(sqlSessionFactory);
}
}
org.mybatis.spring.SqlSessionTemplate#SqlSessionTemplate(org.apache.ibatis.session.SqlSessionFactory, org.apache.ibatis.session.ExecutorType, org.springframework.dao.support.PersistenceExceptionTranslator)
//对 sqlSession 产生代理(jdk代理)
this.sqlSessionProxy = (SqlSession) newProxyInstance(
SqlSessionFactory.class.getClassLoader(),
new Class[] { SqlSession.class },
new SqlSessionInterceptor());
mapper 的代理类生成
查看
org.mybatis.spring.mapper.MapperFactoryBean#getObject
对mapper的接口类产生代理类
@Override
public T getObject() throws Exception {
// 进入 SqlSessionTemplate
return getSqlSession().getMapper(this.mapperInterface);
}
org.mybatis.spring.SqlSessionTemplate#getMapper
@Override
public <T> T getMapper(Class<T> type) {
return getConfiguration().getMapper(type, this);
}
org.apache.ibatis.session.Configuration#getMapper
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
return mapperRegistry.getMapper(type, sqlSession);
}
org.apache.ibatis.binding.MapperRegistry#getMapper
// knownMappers 容器是在解析 mapper xml时初始化的
// type 就是 mapper 的接口类
final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
// MapperProxyFactory类 实例化
// sqlSession 就是 SqlSessionTemplate
return mapperProxyFactory.newInstance(sqlSession);
org.apache.ibatis.binding.MapperProxyFactory#newInstance(org.apache.ibatis.session.SqlSession)
public T newInstance(SqlSession sqlSession) {
final MapperProxy<T> mapperProxy =
new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
return newInstance(mapperProxy);
}
// 产生jdk代理类
// mapperInterface 是 mapper的接口类
// mapperProxy 是代理通知实现类,即实现 InvocationHandler 接口
protected T newInstance(MapperProxy<T> mapperProxy) {
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
}
可以看出在依赖注入 mapper接口时,其实注入的是MapperProxy ,即mapper的代理类,
调用 mapper 接口方法时,会调用到 org.apache.ibatis.binding.MapperProxy#invoke
查看
org.apache.ibatis.binding.MapperProxy#invoke
final MapperMethod mapperMethod = cachedMapperMethod(method);
org.apache.ibatis.binding.MapperProxy#cachedMapperMethod
MapperMethod mapperMethod = methodCache.get(method);
if (mapperMethod == null) {
//查看 MapperMethod
mapperMethod = new MapperMethod(mapperInterface, method, sqlSession.getConfiguration());
methodCache.put(method, mapperMethod);
}
org.apache.ibatis.binding.MapperMethod#MapperMethod
this.command = new SqlCommand(config, mapperInterface, method);
this.method = new MethodSignature(config, mapperInterface, method);
SqlCommand
org.apache.ibatis.binding.MapperMethod.SqlCommand#SqlCommand
final String methodName = method.getName();
final Class<?> declaringClass = method.getDeclaringClass();
//根据方法名找到 MappedStatement 对象,MappedStatement 对象是在解析 mapper xml时初始化的
// MappedStatement 中的 sqlSource 就是 执行sql的信息
MappedStatement ms = resolveMappedStatement(mapperInterface, methodName,
declaringClass,configuration);
返回到
org.apache.ibatis.binding.MapperMethod#MapperMethod
this.command = new SqlCommand(config, mapperInterface, method);
// 查看该方法
this.method = new MethodSignature(config, mapperInterface, method);
org.apache.ibatis.binding.MapperMethod.MethodSignature#MethodSignature
// 获取 mapper 方法的返回值类型
Type resolvedReturnType = TypeParameterResolver.resolveReturnType(method, mapperInterface);
//判断返回类型是否是 void
this.returnsVoid = void.class.equals(this.returnType);
//判断返回类型是否是 集合
this.returnsMany = (configuration.getObjectFactory().isCollection(this.returnType) ||
this.returnType.isArray());
this.returnsCursor = Cursor.class.equals(this.returnType);
//判断方法参数上为 RowBounds 类型的是第几个,即参数的索引
this.rowBoundsIndex = getUniqueParamIndex(method, RowBounds.class);
///判断方法参数上为 ResultHandler类型的是第几个,即参数的索引
this.resultHandlerIndex = getUniqueParamIndex(method, ResultHandler.class);
mapper接口方法的执行
返回到
org.apache.ibatis.binding.MapperProxy#invoke
mapper 接口中的方法真正执行
return mapperMethod.execute(sqlSession, args);
org.apache.ibatis.binding.MapperMethod#execute
switch (command.getType()) {
case INSERT: {
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:
//当前sql为查询时
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);
}
break;
case FLUSH:
result = sqlSession.flushStatements();
break;
default:
throw new BindingException("Unknown execution method for: " + command.getName());
}
org.mybatis.spring.SqlSessionTemplate#selectOne(java.lang.String, java.lang.Object)
@Override
public <T> T selectOne(String statement, Object parameter) {
return this.sqlSessionProxy.<T> selectOne(statement, parameter);
}
通过上面分析,得知 sqlSession 会有一个代理类,即 SqlSessionInterceptor,所以调用sqlSession方法时会进入到代理类 SqlSessionInterceptor#invoke
查看sqlSession 代理通知类
org.apache.ibatis.session.SqlSessionManager.SqlSessionInterceptor#invoke
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//获取 sqlSession
SqlSession sqlSession = getSqlSession(
SqlSessionTemplate.this.sqlSessionFactory,
SqlSessionTemplate.this.executorType,
SqlSessionTemplate.this.exceptionTranslator);
try {
//SqlSession中方法执行的结果
Object result = method.invoke(sqlSession, args);
if (!isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) {
sqlSession.commit(true);
}
return result;
} catch (Throwable t) {
Throwable unwrapped = unwrapThrowable(t);
throw unwrapped;
} finally {
if (sqlSession != null) {
closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
}
}
}
org.mybatis.spring.SqlSessionUtils#getSqlSession(org.apache.ibatis.session.SqlSessionFactory, org.apache.ibatis.session.ExecutorType, org.springframework.dao.support.PersistenceExceptionTranslator)
session = sessionFactory.openSession(executorType);
org.apache.ibatis.session.defaults.DefaultSqlSessionFactory#openSession(org.apache.ibatis.session.ExecutorType)
return openSessionFromDataSource(execType, null, false);
org.apache.ibatis.session.defaults.DefaultSqlSessionFactory#openSessionFromDataSource
// Executor :mybatis执行器,负责Sql的生成和查询
final Executor executor = configuration.newExecutor(tx, execType);
return new DefaultSqlSession(configuration, executor, autoCommit);
org.apache.ibatis.session.Configuration#newExecutor(org.apache.ibatis.transaction.Transaction, org.apache.ibatis.session.ExecutorType)
public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
executorType = executorType == null ? defaultExecutorType : executorType;
executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
Executor executor;
if (ExecutorType.BATCH == executorType) {
executor = new BatchExecutor(this, transaction);
} else if (ExecutorType.REUSE == executorType) {
executor = new ReuseExecutor(this, transaction);
} else {
//默认使用这个
executor = new SimpleExecutor(this, transaction);
}
if (cacheEnabled) {
executor = new CachingExecutor(executor);
}
// mybatis 插件执行,即sql拦截器
executor = (Executor) interceptorChain.pluginAll(executor);
return executor;
}
mybatis 插件 在 mybatis的全局配置文件中配置
返回到
org.mybatis.spring.SqlSessionTemplate.SqlSessionInterceptor#invoke
// SqlSession中方法执行的结果,SqlSession 对象是 DefaultSqlSession
Object result = method.invoke(sqlSession, args);
例如DefaultSqlSession#selectOne 方法执行
org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne(java.lang.String, java.lang.Object)
@Override
public <T> T selectOne(String statement, Object parameter) {
// Popular vote was to return null on 0 results and throw exception on too many.
List<T> list = this.<T>selectList(statement, parameter);
if (list.size() == 1) {
return list.get(0);
} else if (list.size() > 1) {
throw new TooManyResultsException("Expected one result (or null) to be returned by selectOne(), but found: " + list.size());
} else {
return null;
}
}
@Override
public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
try {
// statement 是mapper xml定义的mapper的命名空间加方法的字符串
// 每个方法都会封装成 MappedStatement 对象
MappedStatement ms = configuration.getMappedStatement(statement);
//mybatis执行器操作,如果配置有mybatis的插件时,则会进入到配置的插件中
// 查看 query 方法,见下
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();
}
}
wrapCollection(parameter) 查数包装
从这里可以看出,在使有 foreach 标签时,默认 collection 元素值 使用这里定义的别名中取值
private Object wrapCollection(final Object object) {
if (object instanceof Collection) {
StrictMap<Object> map = new StrictMap<Object>();
map.put("collection", object);
if (object instanceof List) {
map.put("list", object);
}
return map;
} else if (object != null && object.getClass().isArray()) {
StrictMap<Object> map = new StrictMap<Object>();
map.put("array", object);
return map;
}
return object;
}
org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)
@Override
public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
//查看 getBoundSql,分析:DynamicSqlSource
BoundSql boundSql = ms.getBoundSql(parameterObject);
CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql);
return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}
org.apache.ibatis.scripting.xmltags.DynamicSqlSource#getBoundSql
DynamicContext context = new DynamicContext(configuration, parameterObject);
//例如,调到 IfSqlNode#apply
// 执行完下面的方法 apply,此时 DynamicContext#sqlBuilder 中会有一个完整的sql,
// 这个sql就是动态生成后的,最终需要执行的sql语句
// 例如sqlBuilder中的最终sql: SELECT * from t_user WHERE id=#{id}
rootSqlNode.apply(context);
IfSqlNode#apply
org.apache.ibatis.scripting.xmltags.IfSqlNode#apply
@Override
public boolean apply(DynamicContext context) {
// 判断 test 中的表达式是否成立
// test: 表达式字符串
// context.getBindings() mapper方法的参数信息
if (evaluator.evaluateBoolean(test, context.getBindings())) {
//成立时,则迭代下一个,因为动态标签中可能有多个sqlNode
contents.apply(context);
return true;
}
return false;
}
返回到
org.apache.ibatis.scripting.xmltags.DynamicSqlSource#getBoundSql
@Override
public BoundSql getBoundSql(Object parameterObject) {
DynamicContext context = new DynamicContext(configuration, parameterObject);
rootSqlNode.apply(context);
//上面已将动态的sql解析成 需要执行的sql,但是还未解析 例如:#{id} 这样的格式
SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration);
Class<?> parameterType = parameterObject == null ? Object.class : parameterObject.getClass();
// 解析 #{} 的格式,查看 parse 方法
SqlSource sqlSource = sqlSourceParser.parse(context.getSql(), parameterType, context.getBindings());
BoundSql boundSql = sqlSource.getBoundSql(parameterObject);
for (Map.Entry<String, Object> entry : context.getBindings().entrySet()) {
boundSql.setAdditionalParameter(entry.getKey(), entry.getValue());
}
return boundSql;
}
org.apache.ibatis.builder.SqlSourceBuilder#parse
public SqlSource parse(String originalSql, Class<?> parameterType, Map<String, Object> additionalParameters) {
ParameterMappingTokenHandler handler = new ParameterMappingTokenHandler(configuration, parameterType, additionalParameters);
GenericTokenParser parser = new GenericTokenParser("#{", "}", handler);
// 将sql中的 #{} 变为了 ?
// 例如:SELECT * from t_user WHERE id=?
String sql = parser.parse(originalSql);
return new StaticSqlSource(configuration, sql, handler.getParameterMappings());
}
查看
parser.parse(originalSql)
方法,其中handler.handleToken(expression.toString())
会用调用到
org.apache.ibatis.builder.SqlSourceBuilder.ParameterMappingTokenHandler#handleToken
会返回一个 ? 字符。
为什么将 #{} 变为了 ?,因为jdbc要预编译,预编译必须要用?做为占位符
org.apache.ibatis.builder.SqlSourceBuilder.ParameterMappingTokenHandler#handleToken
@Override
public String handleToken(String content) {
// 查看 buildParameterMapping 方法
parameterMappings.add(buildParameterMapping(content));
return "?";
}
org.apache.ibatis.builder.SqlSourceBuilder.ParameterMappingTokenHandler#buildParameterMapping
Map<String, String> propertiesMap = parseParameterMapping(content);
String property = propertiesMap.get("property");
for (Map.Entry<String, String> entry : propertiesMap.entrySet()) {
String name = entry.getKey();
String value = entry.getValue();
if ("javaType".equals(name)) {
javaType = resolveClass(value);
builder.javaType(javaType);
} else if ("jdbcType".equals(name)) {
builder.jdbcType(resolveJdbcType(value));
} else if ("mode".equals(name)) {
builder.mode(resolveParameterMode(value));
} else if ("numericScale".equals(name)) {
builder.numericScale(Integer.valueOf(value));
} else if ("resultMap".equals(name)) {
builder.resultMapId(value);
} else if ("typeHandler".equals(name)) {
typeHandlerAlias = value;
} else if ("jdbcTypeName".equals(name)) {
builder.jdbcTypeName(value);
} else if ("property".equals(name)) {
// Do Nothing
} else if ("expression".equals(name)) {
throw new BuilderException("Expression based parameters are not supported yet");
} else {
throw new BuilderException("An invalid property '" + name + "' was found in mapping #{" + content + "}. Valid properties are " + parameterProperties);
}
}
返回到
org.apache.ibatis.scripting.xmltags.DynamicSqlSource#getBoundSql
SqlSource sqlSource = sqlSourceParser.parse(context.getSql(), parameterType,
context.getBindings());
BoundSql boundSql = sqlSource.getBoundSql(parameterObject);
BoundSql 类中的属性
- sql
被 执行的sql ,例如 SELECT * from t_user WHERE id=?- parameterObject
被 执行的sql的入参信息
返回到
org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)
@Override
public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
//上面已解析
BoundSql boundSql = ms.getBoundSql(parameterObject);
CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql);
//查看该方法
return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}
org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)
return delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
org.apache.ibatis.executor.BaseExecutor#query
list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
org.apache.ibatis.executor.BaseExecutor#queryFromDatabase
list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
org.apache.ibatis.executor.SimpleExecutor#doQuery
Configuration configuration = ms.getConfiguration();
// newStatementHandler 这里有mybatis的拦截器的入口
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
stmt = prepareStatement(handler, ms.getStatementLog());
return handler.<E>query(stmt, resultHandler);
org.apache.ibatis.session.Configuration#newStatementHandler
// 查看 RoutingStatementHandler
StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);
statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
return statementHandler;
org.apache.ibatis.executor.statement.RoutingStatementHandler#RoutingStatementHandler
switch (ms.getStatementType()) {
case STATEMENT:
delegate = new SimpleStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
break;
case PREPARED:
//预编译类型,会走到这里,查看 PreparedStatementHandler
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());
}
查看 PreparedStatementHandler 的父类
org.apache.ibatis.executor.statement.BaseStatementHandler#BaseStatementHandler
// 返回代理对象,负责对用户传递的参数转换成 Jdbc statement 所需要的参数
this.parameterHandler = configuration.newParameterHandler(mappedStatement, parameterObject, boundSql);
// 返回代理对象,jdbc 返回的 ResultSet结果集转成List类的集合
this.resultSetHandler = configuration.newResultSetHandler(executor, mappedStatement, rowBounds, parameterHandler, resultHandler, boundSql);
返回到
org.apache.ibatis.executor.SimpleExecutor#doQuery
stmt = prepareStatement(handler, ms.getStatementLog());
org.apache.ibatis.executor.SimpleExecutor#prepareStatement
private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
Statement stmt;
//这里获取的是Connection 的代理对象
Connection connection = getConnection(statementLog);
//初始化 Statement 对象
stmt = handler.prepare(connection, transaction.getTimeout());
//设置预编译参数的值,即设置占位符的参数值
handler.parameterize(stmt);
return stmt;
}
org.apache.ibatis.type.TypeHandlerRegistry类中注册了 javaType 和 JdbcType的类型处理器,根据传参的参数类型获取对应的处理器
org.apache.ibatis.executor.statement.BaseStatementHandler#prepare
//查看该方法
statement = instantiateStatement(connection);
setStatementTimeout(statement, transactionTimeout);
setFetchSize(statement);
return statement;
org.apache.ibatis.executor.statement.PreparedStatementHandler#instantiateStatement
@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() != null) {
return connection.prepareStatement(sql, mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY);
} else {
//调用这个方法时,会进入到代理对象类中,connection对象其实是个代理
return connection.prepareStatement(sql);
}
}
org.apache.ibatis.logging.jdbc.ConnectionLogger#invoke
if (Object.class.equals(method.getDeclaringClass())) {
return method.invoke(this, params);
}
if ("prepareStatement".equals(method.getName())) {
if (isDebugEnabled()) {
debug(" Preparing: " + removeBreakingWhitespace((String) params[0]), true);
}
PreparedStatement stmt = (PreparedStatement) method.invoke(connection, params);
// 对PreparedStatement 进行代理
stmt = PreparedStatementLogger.newInstance(stmt, statementLog, queryStack);
return stmt;
} else if ("prepareCall".equals(method.getName())) {
if (isDebugEnabled()) {
debug(" Preparing: " + removeBreakingWhitespace((String) params[0]), true);
}
PreparedStatement stmt = (PreparedStatement) method.invoke(connection, params);
stmt = PreparedStatementLogger.newInstance(stmt, statementLog, queryStack);
return stmt;
} else if ("createStatement".equals(method.getName())) {
Statement stmt = (Statement) method.invoke(connection, params);
stmt = StatementLogger.newInstance(stmt, statementLog, queryStack);
return stmt;
} else {
return method.invoke(connection, params);
}
返回到
org.apache.ibatis.executor.SimpleExecutor#prepareStatement
//stmt 就是一个代理对象,见上面解析
stmt = handler.prepare(connection, transaction.getTimeout());
//设置参数,内部方法:typeHandler.setParameter(ps, i + 1, value, jdbcType);
handler.parameterize(stmt);
Statement 设置值时,会 stmt.setString(设置sql中?的参数的索引,参数值)
返回到
org.apache.ibatis.executor.SimpleExecutor#doQuery
stmt = prepareStatement(handler, ms.getStatementLog());
//查看该方法
return handler.<E>query(stmt, resultHandler);
org.apache.ibatis.executor.statement.PreparedStatementHandler#query
@Override
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
PreparedStatement ps = (PreparedStatement) statement;
//sql真正的执行
ps.execute();
// sql结果集的处理
return resultSetHandler.<E> handleResultSets(ps);
}
sql执行结果的返回封装
org.apache.ibatis.executor.resultset.DefaultResultSetHandler#handleResultSets
int resultSetCount = 0;
//查看该方法
ResultSetWrapper rsw = getFirstResultSet(stmt);
int resultMapCount = resultMaps.size();
List<ResultMap> resultMaps = mappedStatement.getResultMaps();
while (rsw != null && resultMapCount > resultSetCount) {
ResultMap resultMap = resultMaps.get(resultSetCount);
// 对sql的结果集进行处理
handleResultSet(rsw, resultMap, multipleResults, null);
rsw = getNextResultSet(stmt);
cleanUpAfterHandlingResultSet();
resultSetCount++;
}
getFirstResultSet
private ResultSetWrapper getFirstResultSet(Statement stmt) throws SQLException {
//获取sql执行的结果集
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 resultset
break;
}
}
}
// 查看该方法 ResultSetWrapper
return rs != null ? new ResultSetWrapper(rs, configuration) : null;
}
org.apache.ibatis.executor.resultset.ResultSetWrapper#ResultSetWrapper
public ResultSetWrapper(ResultSet rs, Configuration configuration) throws SQLException {
super();
// 从配置中获取 类型转换器
this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();
this.resultSet = rs;
// sql执行后的元信息,
final ResultSetMetaData metaData = rs.getMetaData();
final int columnCount = metaData.getColumnCount();
for (int i = 1; i <= columnCount; i++) {
columnNames.add(configuration.isUseColumnLabel() ? metaData.getColumnLabel(i) : metaData.getColumnName(i));
//每一列的类型
jdbcTypes.add(JdbcType.forCode(metaData.getColumnType(i)));
classNames.add(metaData.getColumnClassName(i));
}
}
handleResultSet
org.apache.ibatis.executor.resultset.DefaultResultSetHandler#handleResultSet
if (resultHandler == null) {
DefaultResultHandler defaultResultHandler = new DefaultResultHandler(objectFactory);
//查看该方法
handleRowValues(rsw, resultMap, defaultResultHandler, rowBounds, null);
multipleResults.add(defaultResultHandler.getResultList());
}
org.apache.ibatis.executor.resultset.DefaultResultSetHandler#handleRowValues
handleRowValuesForSimpleResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
org.apache.ibatis.executor.resultset.DefaultResultSetHandler#handleRowValuesForSimpleResultMap
// 跳过分页
skipRows(rsw.getResultSet(), rowBounds);
// rsw.getResultSet().next() 循环每一行的记录
while (shouldProcessMoreRows(resultContext, rowBounds) && rsw.getResultSet().next()) {
//循环每一行,封装每一行的值到对象中
Object rowValue = getRowValue(rsw, discriminatedResultMap);
}
RowBounds 逻辑分页,一般不用 offset 从哪一个记录开始, limit 查询出记录的个数
org.apache.ibatis.executor.resultset.DefaultResultSetHandler#getRowValue(org.apache.ibatis.executor.resultset.ResultSetWrapper, org.apache.ibatis.mapping.ResultMap)
// 创建一个要返回的空对象
Object rowValue = createResultObject(rsw, resultMap, lazyLoader, null);
foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, null) || foundValues;
org.apache.ibatis.executor.resultset.DefaultResultSetHandler#applyPropertyMappings
// 这个就是mapper xml中的 resultMap
final List<ResultMapping> propertyMappings = resultMap.getPropertyResultMappings();
for (ResultMapping propertyMapping : propertyMappings) {
//mapper xml中的 resultMap中的每一行处理,也就是每一列的处理
Object value = getPropertyMappingValue(rsw.getResultSet(), metaObject, propertyMapping, lazyLoader, columnPrefix);
// 将值设置到上面创建的空对象中
metaObject.setValue(property, value);
}
getPropertyMappingValue
org.apache.ibatis.executor.resultset.DefaultResultSetHandler#getPropertyMappingValue
// 类型
final TypeHandler<?> typeHandler = propertyMapping.getTypeHandler();
// 根据列名获取值
return typeHandler.getResult(rs, column);
org.apache.ibatis.type.BaseTypeHandler#getResult(java.sql.ResultSet, java.lang.String)
result = getNullableResult(rs, columnName);
根据相应的类型处理器处理值
返回到
org.apache.ibatis.executor.resultset.DefaultResultSetHandler#handleRowValuesForSimpleResultMap
Object rowValue = getRowValue(rsw, discriminatedResultMap);
storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());
org.apache.ibatis.executor.resultset.DefaultResultSetHandler#storeObject
callResultHandler(resultHandler, resultContext, rowValue);
org.apache.ibatis.executor.resultset.DefaultResultSetHandler#callResultHandler
private void callResultHandler(ResultHandler<?> resultHandler, DefaultResultContext<Object> resultContext, Object rowValue) {
resultContext.nextResultObject(rowValue);
//查看 handleResult 方法
((ResultHandler<Object>) resultHandler).handleResult(resultContext);
}
org.apache.ibatis.executor.result.DefaultResultHandler#handleResult
将封装的结果对象添加到list中
@Override
public void handleResult(ResultContext<? extends Object> context) {
list.add(context.getResultObject());
}