目录
1. mapperProxy调用业务方法,实则调用invoke
3. 进2的sqlSession.selectOne实则defaultSqlSession.selectOne
4. 进3的defaultSqlSession.selectList
5. 进4的configuration.getMappedStatement(statement)
7. 进6的mappedStatement.getBoundSql
8. 进6的executor.query(... key, boundSql)
9. 进8的delegate.query(delegate为simpleExecutor)
10. 进9的baseExecutor.queryFromDatabase
11. 进10的simpleExecutor.doQuery
12. 进11的configuration.newStatementHandler
13. 进12的new RountingStatementHandler
14. 进13的new BaseStatementHandler
15. 进12的interceptorChain.pluginAll
16. 进11的simpleExecutor.prepareStatement
17. 进16的baseExecutor.getConnection(statementLog)
18. 进16的baseStatementHandler.prepare
19. 进16的routingStatementHandler.parameterize
20. 进19的prepareStatementHandler.parameterize
21. 进20的defaultParameterHandler.setParameters
22. 进11的rountingStatementHandler.query
23. 进22的preparedStatementHandler.query
24. 进23的resultSetHandler.handleResultSets
25. 进24的,层层跳转,最后跳到DefaultResultSetHandler的applyAutomaticMappings
1. mapperProxy调用业务方法,实则调用invoke
// method就是EmployeeMapper定义的抽象方法:
// public abstract org.example.bean.Employee org.example.dao.EmployeeMapper.getEmpById(java.lang.Integer)
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
if (Object.class.equals(method.getDeclaringClass())) {
return method.invoke(this, args);
} else if (method.isDefault()) {
// 默认方法是一个公共的非抽象实例方法,也就是说,在接口类型中声明的具有主体的非静态方法。
if (privateLookupInMethod == null) {
return invokeDefaultMethodJava8(proxy, method, args);
} else {
return invokeDefaultMethodJava9(proxy, method, args);
}
}
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
// 将方法置于methodCache缓存中,
// public abstract org.example.bean.Employee org.example.dao.EmployeeMapper.getEmpById(java.lang.Integer)
// 然后返回一个MapperMethod对象,这个对象包含了command指令以及method方法的一些属性,
// 比如指令名为org.example.dao.EmployeeMapper.getEmpById,指令类型为SELECT。
// 方法returnsMap为false,returnType为class org.example.bean.Employee等
final MapperMethod mapperMethod = cachedMapperMethod(method);
// execute判断增删改查类型,包装参数
return mapperMethod.execute(sqlSession, args);
}
2. 进1的mapperMethod.execute
// args还是我们输入的id值,Object[1],便于后面占位符赋值
public Object execute(SqlSession sqlSession, Object[] args) {
Object result;
// 判断指令的类型,上面说了是SELECT
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:
// 判断方法的一些属性
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 {
// 将参数都转化为能被sql占位符赋值的对象
Object param = method.convertArgsToSqlCommandParam(args);
// sqlSession.selectOne实际就调用DefaultSqlSession里的selectOne
// 指令名为org.example.dao.EmployeeMapper.getEmpById
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;
}
3. 进2的sqlSession.selectOne实则defaultSqlSession.selectOne
@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.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;
}
}
4. 进3的defaultSqlSession.selectList
// statement就是org.example.dao.EmployeeMapper.getEmpById
@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();
}
}
5. 进4的configuration.getMappedStatement(statement)
public MappedStatement getMappedStatement(String id, boolean validateIncompleteStatements) {
if (validateIncompleteStatements) {
// 从mapper配置文件获取所有的唯一标识的mappedStatement(包含了你配置的属性等),唯一标识也就是每个方法名
// 比如deleteEmpById、org.example.dao.EmployeeMapper.getEmpByIdReturnMap等
buildAllStatements();
}
// 这里就是根据方法名,得到mapper配置文件中对应的statement
return mappedStatements.get(id);
}
6. 进4的executor.query
看下执行器类
以CachingExecutor为例
@Override
public <E> List<E> query(MappedStatement ms, Object parameterObject
, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
// 获取包含sql语句详细信息的BoundSql
BoundSql boundSql = ms.getBoundSql(parameterObject);
// 获取缓存的键,如-101660062:1751857674:org.example.dao.EmployeeMapper.getEmpById:0:2147483647:
// select id,last_name,email,gender from employee where id = ?:1:development
// 获取缓存的键cacheKey
CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql);
return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}
7. 进6的mappedStatement.getBoundSql
public BoundSql getBoundSql(Object parameterObject) {
// 这里的BoundSql的sql就是select id,last_name,email,gender from employee where id = ?
BoundSql boundSql = sqlSource.getBoundSql(parameterObject);
// ParameterMapping{property='id', mode=IN, javaType=class java.lang.Object
// , jdbcType=null, numericScale=null, resultMapId='null', jdbcTypeName='null', expression='null'}
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
if (parameterMappings == null || parameterMappings.isEmpty()) {
boundSql = new BoundSql(configuration, boundSql.getSql()
, parameterMap.getParameterMappings(), parameterObject);
}
// 检查有没有参数映射中的嵌套结果映射ResultMap
for (ParameterMapping pm : boundSql.getParameterMappings()) {
String rmId = pm.getResultMapId();
if (rmId != null) {
ResultMap rm = configuration.getResultMap(rmId);
if (rm != null) {
hasNestedResultMaps |= rm.hasNestedResultMaps();
}
}
}
return boundSql;
}
8. 进6的executor.query(... key, boundSql)
@Override
public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds
, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)
throws SQLException {
Cache cache = ms.getCache();
if (cache != null) {
flushCacheIfRequired(ms);
if (ms.isUseCache() && resultHandler == null) {
ensureNoOutParams(ms, boundSql);
@SuppressWarnings("unchecked")
List<E> list = (List<E>) tcm.getObject(cache, key);
if (list == null) {
list = delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
tcm.putObject(cache, key, list); // issue #578 and #116
}
return list;
}
}
// delegate为SimpleExecutor
return delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}
9. 进8的delegate.query(delegate为simpleExecutor)
这里是调用simpleExecutor的父类baseExecutor的query
@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++;
// 查询本地缓存有无数据,没有就调用queryFromDatabase,查出后也会保存到本地缓存
list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;
if (list != null) {
handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
} else {
list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
}
} finally {
queryStack--;
}
if (queryStack == 0) {
for (BaseExecutor.DeferredLoad deferredLoad : deferredLoads) {
deferredLoad.load();
}
// issue #601
deferredLoads.clear();
if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
// issue #482
clearLocalCache();
}
}
return list;
}
10. 进9的baseExecutor.queryFromDatabase
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 {
// 从数据库获取数据
list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
} finally {
localCache.removeObject(key);
}
// 将上面的缓存key存到本地缓存作键,结果作值
localCache.putObject(key, list);
if (ms.getStatementType() == StatementType.CALLABLE) {
localOutputParameterCache.putObject(key, parameter);
}
return list;
}
11. 进10的simpleExecutor.doQuery
@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);
// SimpleExecutor的prepareStatement
stmt = prepareStatement(handler, ms.getStatementLog());
return handler.query(stmt, resultHandler);
} finally {
closeStatement(stmt);
}
}
12. 进11的configuration.newStatementHandler
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) interceptorChain.pluginAll(statementHandler);
return statementHandler;
}
13. 进12的new RountingStatementHandler
public RoutingStatementHandler(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds
, ResultHandler resultHandler, BoundSql boundSql) {
// 根据mappedStatement的statementType去创建SimpleStatementHandler
// 或PreparedStatementHandler或CallableStatementHandler
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());
}
}
14. 进13的new BaseStatementHandler
无论new SimpleStatementHandler还是其它,都会初始化为父类构造器
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;
this.parameterHandler = configuration.newParameterHandler(mappedStatement, parameterObject, boundSql);
this.resultSetHandler = configuration.newResultSetHandler(executor, mappedStatement, rowBounds, parameterHandler, resultHandler, boundSql);
}
于是初始化顺序是,先生成ParamenterHandler,拦截器包装,再生成ResultSetHandler,拦截器包装,最后再生成SimpleStatementHandler或PreparedStatementHandler或CallableStatementHandler,再拦截器包装。
15. 进12的interceptorChain.pluginAll
注意每一次包装都是返回目标对象的一个代理对象
public Object pluginAll(Object target) {
// 逐层包装
for (Interceptor interceptor : interceptors) {
target = interceptor.plugin(target);
}
return target;
}
16. 进11的simpleExecutor.prepareStatement
private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
Statement stmt;
// 从事务中获取数据库连接对象(debug时是代理对象ConnectionLogger)
Connection connection = getConnection(statementLog);
// 将占位符识别预处理下,但还不是替换为参数值
stmt = handler.prepare(connection, transaction.getTimeout());
// 参数化,sql语句加上了参数
handler.parameterize(stmt);
return stmt;
}
17. 进16的baseExecutor.getConnection(statementLog)
protected Connection getConnection(Log statementLog) throws SQLException {
// 从事务中获取数据库连接对象
Connection connection = transaction.getConnection();
if (statementLog.isDebugEnabled()) {
// debug时是代理对象ConnectionLogger
return ConnectionLogger.newInstance(connection, statementLog, queryStack);
} else {
return connection;
}
}
18. 进16的baseStatementHandler.prepare
// 预编译sql产生PreparedStatement对象
@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);
}
}
19. 进16的routingStatementHandler.parameterize
@Override
public void parameterize(Statement statement) throws SQLException {
delegate.parameterize(statement);
}
20. 进19的prepareStatementHandler.parameterize
@Override
public void parameterize(Statement statement) throws SQLException {
parameterHandler.setParameters((PreparedStatement) statement);
}
21. 进20的defaultParameterHandler.setParameters
// 设置参数
@Override
public void setParameters(PreparedStatement ps) {
ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
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;
} 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) {
jdbcType = configuration.getJdbcTypeForNull();
}
try {
// 给sql预编译设置参数
typeHandler.setParameter(ps, i + 1, value, jdbcType);
} catch (TypeException | SQLException e) {
throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);
}
}
}
}
}
22. 进11的rountingStatementHandler.query
@Override
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
return delegate.query(statement, resultHandler);
}
23. 进22的preparedStatementHandler.query
@Override
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
PreparedStatement ps = (PreparedStatement) statement;
// 执行sql语句
ps.execute();
// 返回结果集数据
return resultSetHandler.handleResultSets(ps);
}
24. 进23的resultSetHandler.handleResultSets
// 使用ResultSetHandler处理结果,使用TypeHandler获取value值
@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;
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);
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++;
}
}
}
25. 进24的,层层跳转,最后跳到DefaultResultSetHandler的applyAutomaticMappings
private boolean applyAutomaticMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String columnPrefix) throws SQLException {
List<DefaultResultSetHandler.UnMappedColumnAutoMapping> autoMapping = createAutomaticMappings(rsw, resultMap, metaObject, columnPrefix);
boolean foundValues = false;
if (!autoMapping.isEmpty()) {
for (DefaultResultSetHandler.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;
}
可见,调用typeHandler.getResult获取value值