ibatis延迟加载

    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。

你可能感兴趣的:(ibatis延迟加载)