Ibatis获取查询的结果是从ResultMap.java类里面的getResults获取
/**
* Read a row from a resultset and map results to an array.
*
* @param statementScope scope of the request
* @param rs ResultSet to read from
*
* @return row read as an array of column values.
*
* @throws java.sql.SQLException
*/
public Object[] getResults(StatementScope statementScope, ResultSet rs)
throws SQLException {
...
for (int i = 0; i < getResultMappings().length; i++) {
...
columnValues[i] = getNestedSelectMappingValue(statementScope, rs, mapping, javaType);
...
}
}
getNestedSelectMappingValue方法的调用如下:
protected Object getNestedSelectMappingValue(StatementScope statementScope, ResultSet rs, ResultMapping mapping, Class targetType)
throws SQLException {
try {
...
result = ResultLoader.loadResult(client, statementName, parameterObject, targetType);
...
return result;
} catch (InstantiationException e) {
throw new NestedSQLException("Error setting nested bean property. Cause: " + e, e);
} catch (IllegalAccessException e) {
throw new NestedSQLException("Error setting nested bean property. Cause: " + e, e);
}
}
这时调用的是ResultLoader.loadResult方法:
/**
* Loads a result lazily
*
* @param client - the client creating the object
* @param statementName - the name of the statement to be used
* @param parameterObject - the parameters for the statement
* @param targetType - the target type of the result
* @return the loaded result
* @throws SQLException
*/
public static Object loadResult(SqlMapClientImpl client, String statementName, Object parameterObject, Class targetType)
throws SQLException {
Object value = null;
if (client.isLazyLoadingEnabled()) {
if (client.isEnhancementEnabled()) {
EnhancedLazyResultLoader lazy = new EnhancedLazyResultLoader(client, statementName, parameterObject, targetType);
value = lazy.loadResult();
} else {
LazyResultLoader lazy = new LazyResultLoader(client, statementName, parameterObject, targetType);
value = lazy.loadResult();
}
} else {
value = getResult(client, statementName, parameterObject, targetType);
}
return value;
}
注意下面的调用:
(调用CGLIB的方式代理这里暂不分析,先分析利用java反射API进行的动态代理方式)
LazyResultLoader lazy = new LazyResultLoader(client, statementName, parameterObject, targetType);
value = lazy.loadResult();
LazyResultLoader 是实现InvocationHandler的代理动态类,里面的方法如下:
/**
* Loads the result
*
* @return the results - a list or object
*
* @throws SQLException if there is a problem
*/
public Object loadResult() throws SQLException {
if (Collection.class.isAssignableFrom(targetType)) {
InvocationHandler handler = new LazyResultLoader(client, statementName, parameterObject, targetType);
ClassLoader cl = targetType.getClassLoader();
if (Set.class.isAssignableFrom(targetType)) {
return Proxy.newProxyInstance(cl, SET_INTERFACES, handler);
} else {
return Proxy.newProxyInstance(cl, LIST_INTERFACES, handler);
}
} else {
return ResultLoader.getResult(client, statementName, parameterObject, targetType);
}
}
方法里面对所有的collection作为父接口的类都采用了创建代理对象的方式进行了延迟加载,对所有set的采用的set的方式,所有非set的采用list的方式(也即是对所有的子查询进行了延迟加载)。所有的非collectin子类都采用非延迟加载的方式加载。
这里先创建一个代理对象,待真正用到对象的数据时,将执行动态代理的invoke方法,然后在invoke方法里面才真正的加载数据。
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
if ("finalize".hashCode() == method.getName().hashCode()
&& "finalize".equals(method.getName())) {
return null;
} else {
loadObject();
if (resultObject != null) {
try {
return method.invoke(resultObject, objects);
} catch (Throwable t) {
throw ClassInfo.unwrapThrowable(t);
}
} else {
return null;
}
}
}
private synchronized void loadObject() {
if (!loaded) {
try {
loaded = true;
resultObject = ResultLoader.getResult(client, statementName, parameterObject, targetType);
} catch (SQLException e) {
throw new RuntimeException("Error lazy loading result. Cause: " + e, e);
}
}
}
实际的加载数据是通过ResultLoader.getResult(client, statementName, parameterObject, targetType);里面的实际加载委托为SqlMapClientImpl的数据加载:
protected static Object getResult(SqlMapClientImpl client, String statementName, Object parameterObject, Class targetType) throws SQLException {
Object value = null;
if (DomCollectionTypeMarker.class.isAssignableFrom(targetType)) {
value = client.queryForList(statementName, parameterObject);
} else if (Set.class.isAssignableFrom(targetType)) {
value = new HashSet(client.queryForList(statementName, parameterObject));
} else if (Collection.class.isAssignableFrom(targetType)) {
value = client.queryForList(statementName, parameterObject);
} else if (targetType.isArray()) {
List list = client.queryForList(statementName, parameterObject);
value = listToArray(list, targetType.getComponentType());
} else {
value = client.queryForObject(statementName, parameterObject);
}
return value;
}
备注:初稿,为写完,后续继续。
分享到:
相关推荐
1.iBatis2学习笔记:基本原理和配置.doc 2.iBatis2学习笔记:与Spring2的整合.doc 3.iBatis2学习笔记:单表映射 .doc 4.iBatis2学习笔记:SqlMap的配置总结(18条).doc 5.iBatis2学习笔记:入参和返回值的问题.doc ...
ibatis的原码 ibatis源码 ibatis源码 ibatis源码
ibatis源码 学习参考 对于学习ibatis很有帮助
ibatis框架源码剖析书中附带的光盘,ibatis源码分析
iBATIS框架源码剖析源码 iBATIS框架源码剖析源码 iBATIS框架源码剖析源码
iBATIS框架源码剖析
mybatis的前身ibatis源码剖析
iBATIS一词来源于“internet”和“abatis”的组合,是一个由Clinton Begin在2001年发起的开放源代码项目。于2010年6月16号被谷歌托管,改名为MyBatis。是一个基于SQL映射支持Java和·NET的持久层框架。
实现ibatis手动控制加载sqlmap文件,终于不用重启应用了
PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN" "http://www.ibatis.com/dtd/sql-map-config-2.dtd"> cacheModelsEnabled="true" enhancementEnabled="true" lazyLoadingEnabled="true" ...
IbatisDemo 博文链接:https://xdjava.iteye.com/blog/1070408
IBatis3.0学习IBatis3.0学习IBatis3.0学习IBatis3.0学习IBatis3.0学习IBatis3.0学习IBatis3.0学习
ibatis-2.3.4.726.jar,ibatis-2.3.0.677.jar,ibatis-2.3.3.720.jar下载,都已放入一个压缩包下。
springmvc+ibatis写的开发源码,对学习springmvc+ibatis的框架搭建和配置有帮助,下载后能够在eclipse中运行。
iBATIS一词来源于“internet”和“abatis”的组合,是一个由Clinton Begin在2001年发起的开放源代码项目。最初侧重于密码软件的开发,现在是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data ...
ibatis开发指南 ibatis资料文档 ibatis2.x_jar包 ibatis源码 ibatis实践项目
iBATIS框架源码剖析的第二部分,下了他就下完了