查询实现
具体操作
根据id在数据表中查询员工的信息。
源码分析
调用代理对象(MapperProxy)mapper
的.getEmpById
方法:
Employee employee = mapper.getEmpById(1);
因为mapper
是一个InvocationHandler
,在执行目标方法之前会先执行invoke
方法:
其中MapperMethod
的execute()
方法:
先判断增删改查
将参数转换成我们能用的参数,利用参数解析器进行转换,如果参数是单个直接返回,如果是多个包装成Map再返回。
public Object convertArgsToSqlCommandParam(Object[] args) {
return paramNameResolver.getNamedParams(args);
}
查询多个,调用selectOne
:里面调用selectList
查询多个,将他的返回值返回。
selectList
具体实现:
具体的包装过程:
public static Object wrapToMapIfCollection(Object object, String actualParamName) {
if (object instanceof Collection) {
ParamMap<Object> map = new ParamMap<>();
map.put("collection", object);
if (object instanceof List) {
map.put("list", object);
}
Optional.ofNullable(actualParamName).ifPresent(name -> map.put(name, object));
return map;
} else if (object != null && object.getClass().isArray()) {
ParamMap<Object> map = new ParamMap<>();
map.put("array", object);
Optional.ofNullable(actualParamName).ifPresent(name -> map.put(name, object));
return map;
}
return object;
}
}
query
方法:
query
查询:
继续查询:
@SuppressWarnings("unchecked")
@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++;
//从本地缓存中拿到key 先查二级缓存,二级缓存中没有时再查一级缓存
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 (DeferredLoad deferredLoad : deferredLoads) {
deferredLoad.load();
}
// issue #601
deferredLoads.clear();
if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
// issue #482
clearLocalCache();
}
}
return list;
}
queryFromDatabase
的具体实现:
doQuery
的具体实现:
其中的query
的实现:使用resultSetHandler
对查询结果进行封装:使用TypeHandler
获取value
值。
创建StatementHandler
的newStatementHandler
的具体实现:
public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
//实际为创建了PreparedStatementHandler
StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);
//使用拦截器
statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
return statementHandler;
}
调用了RoutingStatementHandler
,创建了一个PreparedStatementHandler
:
创建了一个PreparedStatementHandler
,就是按照构造器创建Handler的过程。
预编译parameterize
的具体实现,预编译时会调用parameterHandler
对象设置参数:
@Override
public void parameterize(Statement statement) throws SQLException {
parameterHandler.setParameters((PreparedStatement) statement);
}
setParameters
的具体实现:
会拿到类型处理器(TypeHandler
),调用类型处理器的setParameter
,ps
为PreparedStatement
还会创建resultSetHandler
对查询的结果进行处理。
查询流程总结
利用代理对象执行增删改查,实际使用代理对象的DefaultSqlSession
,又使用里面的Executor
来执行增删改查,Executor
会创建StatementHandler
(处理sql语句预编译,设置参数等相关工作),StatementHandler
会创建出ParameterHandler
(设置预编译参数用的)和ResultSetHandler
(处理查询后的结果)。设置参数和处理结果都是用TypeHandler
来做的。在整个过程中,TypeHandler
进行数据库类型和javaBean类型的映射。