首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

Ibatis源码学习(2):延迟加载的实现

2012-07-15 
Ibatis源码学习(二):延迟加载的实现Ibatis获取查询的结果是从ResultMap.java类里面的getResults获取?/***

Ibatis源码学习(二):延迟加载的实现

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;  }
?

?

?

备注:初稿,为写完,后续继续。

热点排行