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