1、getLocalSqlMapSession()获取一个SqlMapSessionImpl 相当于JDBC的一个Connection连接

2、SqlMapExecutor -> SqlMapExecutorDelegate.queryForObject(id, paramObject)

  通过id从已加载的配置中获取sql及相关信息,将参数注入,然后执行

 

3、主要执行代码

protected void executeQueryWithCallback(StatementScope statementScope, Connection conn, Object parameterObject, Object resultObject, RowHandler rowHandler, int skipResults, int maxResults)
      throws SQLException {
    ErrorContext errorContext = statementScope.getErrorContext();
    errorContext.setActivity("preparing the mapped statement for execution");
    errorContext.setObjectId(this.getId());
    errorContext.setResource(this.getResource());

    try {
      parameterObject = validateParameter(parameterObject);

      Sql sql = getSql();

      errorContext.setMoreInfo("Check the parameter map.");
      ParameterMap parameterMap = sql.getParameterMap(statementScope, parameterObject);

      errorContext.setMoreInfo("Check the result map.");
      ResultMap resultMap = sql.getResultMap(statementScope, parameterObject);

      statementScope.setResultMap(resultMap);
      statementScope.setParameterMap(parameterMap);

      errorContext.setMoreInfo("Check the parameter map.");
      Object[] parameters = parameterMap.getParameterObjectValues(statementScope, parameterObject);

      errorContext.setMoreInfo("Check the SQL statement.");
    //将sql中的参数#name# 等处理成 ?
      String sqlString = sql.getSql(statementScope, parameterObject);

      errorContext.setActivity("executing mapped statement");
      errorContext.setMoreInfo("Check the SQL statement or the result map.");
      RowHandlerCallback callback = new RowHandlerCallback(resultMap, resultObject, rowHandler);
      sqlExecuteQuery(statementScope, conn, sqlString, parameters, skipResults, maxResults, callback);

      errorContext.setMoreInfo("Check the output parameters.");
      if (parameterObject != null) {
        postProcessParameterObject(statementScope, parameterObject, parameters);
      }

      errorContext.reset();
      sql.cleanup(statementScope);
      notifyListeners();
    } catch (SQLException e) {
      errorContext.setCause(e);
      throw new NestedSQLException(errorContext.toString(), e.getSQLState(), e.getErrorCode(), e);
    } catch (Exception e) {
      errorContext.setCause(e);
      throw new NestedSQLException(errorContext.toString(), e);
    }
  }

 /**
   * Long form of the method to execute a query
   *
   * @param statementScope     - the request scope
   * @param conn        - the database connection
   * @param sql         - the SQL statement to execute
   * @param parameters  - the parameters for the statement
   * @param skipResults - the number of results to skip
   * @param maxResults  - the maximum number of results to return
   * @param callback    - the row handler for the query
   * @throws SQLException - if the query fails
   */
  public void executeQuery(StatementScope statementScope, Connection conn, String sql, Object[] parameters, int skipResults, int maxResults, RowHandlerCallback callback) throws SQLException {
    ErrorContext errorContext = statementScope.getErrorContext();
    errorContext.setActivity("executing query");
    errorContext.setObjectId(sql);
    PreparedStatement ps = null;
    ResultSet rs = null;
    setupResultObjectFactory(statementScope);
    try {
      errorContext.setMoreInfo("Check the SQL Statement (preparation failed).");
      Integer rsType = statementScope.getStatement().getResultSetType();
      if (rsType != null) {
        ps = prepareStatement(statementScope.getSession(), conn, sql, rsType);
      } else {
        ps = prepareStatement(statementScope.getSession(), conn, sql);
      }
      setStatementTimeout(statementScope.getStatement(), ps);
      Integer fetchSize = statementScope.getStatement().getFetchSize();
      if (fetchSize != null) {
        ps.setFetchSize(fetchSize.intValue());
      }
      errorContext.setMoreInfo("Check the parameters (set parameters failed).");
      statementScope.getParameterMap().setParameters(statementScope, ps, parameters);
      errorContext.setMoreInfo("Check the statement (query failed).");
      ps.execute();
      errorContext.setMoreInfo("Check the results (failed to retrieve results).");

      // Begin ResultSet Handling
      rs = handleMultipleResults(ps, statementScope, skipResults, maxResults, callback);
      // End ResultSet Handling
    } finally {
      try {
        closeResultSet(rs);
      } finally {
        closeStatement(statementScope.getSession(), ps);
      }
    }

  }

 

 4、JDBC执行的结果返回到实体类对象(动态代理实现)

    a.通过ResultSet获取元数据信息,列名、列序

 private void initializeBeanResults(ResultSet rs) {
    try {
      ClassInfo classInfo = ClassInfo.getInstance(getResultClass());
      String[] propertyNames = classInfo.getWriteablePropertyNames();

      Map propertyMap = new HashMap();
      for (int i = 0; i < propertyNames.length; i++) {
        propertyMap.put(propertyNames[i].toUpperCase(java.util.Locale.ENGLISH), propertyNames[i]);
      }

      List resultMappingList = new ArrayList();
      ResultSetMetaData rsmd = rs.getMetaData();
      for (int i = 0, n = rsmd.getColumnCount(); i < n; i++) {
        String columnName = getColumnIdentifier(rsmd, i + 1);
        String upperColumnName = columnName.toUpperCase(java.util.Locale.ENGLISH);
        String matchedProp = (String) propertyMap.get(upperColumnName);
        Class type = null;
        if (matchedProp == null) {
          Probe p = ProbeFactory.getProbe(this.getResultClass());
          try {
            type = p.getPropertyTypeForSetter(this.getResultClass(), columnName);
          } catch (Exception e) {
            //TODO - add logging to this class?
          }
        } else {
          type = classInfo.getSetterType(matchedProp);
        }
        if (type != null || matchedProp != null) {
          ResultMapping resultMapping = new ResultMapping();
          resultMapping.setPropertyName((matchedProp != null ? matchedProp : columnName));
          resultMapping.setColumnName(columnName);
          resultMapping.setColumnIndex(i + 1);
          resultMapping.setTypeHandler(getDelegate().getTypeHandlerFactory().getTypeHandler(type)); //map SQL to JDBC type
          resultMappingList.add(resultMapping);
        }
      }
      setResultMappingList(resultMappingList);

    } catch (SQLException e) {
      throw new RuntimeException("Error automapping columns. Cause: " + e);
    }

  }

   b.根据列信息,使用cglib动态代理的方法,创建一个实体对象的代理,有根据列名生成的getter和setter

package com.ibatis.sqlmap.engine.accessplan;

import net.sf.cglib.beans.BulkBean;

/**
 * Enhanced PropertyAccessPlan (for working with beans using CG Lib)
 */
public class EnhancedPropertyAccessPlan extends BaseAccessPlan {

  private BulkBean bulkBean;

  EnhancedPropertyAccessPlan(Class clazz, String[] propertyNames) {
    super(clazz, propertyNames);
    bulkBean = BulkBean.create(clazz, getGetterNames(propertyNames), getSetterNames(propertyNames), getTypes(propertyNames));
  }

  public void setProperties(Object object, Object[] values) {
      //values = new Object[]{"1",1};
      bulkBean.setPropertyValues(object, values);    
  }

  public Object[] getProperties(Object object) {
    return bulkBean.getPropertyValues(object);
  }

}

 c.调用JavaBeanDataExchange(还有其他的DataExchange)中的setData方法

    该方法使用代理对象的setProperties方法对目标对象注入结果值

 public Object setData(StatementScope statementScope, ResultMap resultMap, Object resultObject, Object[] values) {
    if (resultPlan != null) {
      Object object = resultObject;

      ErrorContext errorContext = statementScope.getErrorContext();

      if (object == null) {
        errorContext.setMoreInfo("The error occured while instantiating the result object");
        try {
          object = ResultObjectFactoryUtil.createObjectThroughFactory(resultMap.getResultClass());
        } catch (Exception e) {
          throw new RuntimeException("JavaBeansDataExchange could not instantiate result class.  Cause: " + e, e);
        }
      }
      errorContext.setMoreInfo("The error happened while setting a property on the result object.");
      resultPlan.setProperties(object, values);
      return object;
    } else {
      return null;
    }
  }