ibatis延迟加载

来源:互联网 发布:我的世界js代码大全 编辑:程序博客网 时间:2024/04/28 05:30

    ibaits中延迟加载的含义是在使用到某个对象时,再去加载具体的数据(执行查询语句),否则不会对数据进行加载。

    ibatis查询数据库时,会调用ResultMap.getResults(StatementScope statementScope, ResultSet rs)方法,其实现如下:

  public Object[] getResults(StatementScope statementScope, ResultSet rs)      throws SQLException {    ErrorContext errorContext = statementScope.getErrorContext();    errorContext.setActivity("applying a result map");    errorContext.setObjectId(this.getId());    errorContext.setResource(this.getResource());    errorContext.setMoreInfo("Check the result map.");    boolean foundData = false;    Object[] columnValues = new Object[getResultMappings().length];    for (int i = 0; i < getResultMappings().length; i++) {      ResultMapping mapping = (ResultMapping) getResultMappings()[i];      errorContext.setMoreInfo(mapping.getErrorString());      if (mapping.getStatementName() != null) {        if (resultClass == null) {          throw new SqlMapException("The result class was null when trying to get results for ResultMap named " + getId() + ".");        } else if (Map.class.isAssignableFrom(resultClass)) {          Class javaType = mapping.getJavaType();          if (javaType == null) {            javaType = Object.class;          }          columnValues[i] = getNestedSelectMappingValue(statementScope, rs, mapping, javaType);        } else if (DomTypeMarker.class.isAssignableFrom(resultClass)) {          Class javaType = mapping.getJavaType();          if (javaType == null) {            javaType = DomTypeMarker.class;          }          columnValues[i] = getNestedSelectMappingValue(statementScope, rs, mapping, javaType);        } else {          Probe p = ProbeFactory.getProbe(resultClass);          Class type = p.getPropertyTypeForSetter(resultClass, mapping.getPropertyName());          columnValues[i] = getNestedSelectMappingValue(statementScope, rs, mapping, type);        }        foundData = foundData || columnValues[i] != null;      } else if (mapping.getNestedResultMapName() == null) {        columnValues[i] = getPrimitiveResultMappingValue(rs, mapping);        if (columnValues[i] == null) {          columnValues[i] = doNullMapping(columnValues[i], mapping);        } else {          foundData = true;        }      }    }    statementScope.setRowDataFound(foundData);    return columnValues;  }

    从代码中可以看出,如果在<result>中设置了select属性,会调用方法getNestedSelectMappingValue()。在该方法中调用ResultLoader.loadResult()方法:

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

    在该方法中使用了延迟加载技术。当然,要使用延迟加载,需要在配置文件中设置lazyLoadingEnabled为true。

<settings  lazyLoadingEnabled="true" />

    这样,ibatis才会使用延迟加载,否则,直接执行查询。
    在ibatis中有两个负责延迟加载的类:

    1、LazyResultLoader

    2、EnhancedLazyResultLoader。

    从以上代码可以看出,如果属性enhancementEnabled设置为true,则使用增强的延迟加载。但是要使该属性为true,除了在配置文件里设置enhancementEnabled外,还需要有net.sf.cglib.proxy.InvocationHandler类。

    如果属性enhancementEnabled为false,则使用LazyResultLoader。该类实现了InvocationHandler接口,所以很明显,这种方式使用了动态代理的方式。调用LazyResultLoader.loadResult(),如果目标对象类型是Collection或其子类,则返回一个代理对象,若不是Collection类型,则直接执行查询语句。由此可知,当使用LazyResultLoader来实现延迟加载时,只是对目标对象为Collection类型的数据有效。
    总结:

    LazyResultLoader只能延迟加载Collection类型的属性,而EnhancedLazyResultLoader可以延迟加载Collection类型的属性,以及自定义类型的属性,而且性能方面要优于LazyResultLoader。