mybatis源码解析之运行原理

203 阅读37分钟

1.前言

mybatis用作数据库操作的中间件,相信大家都不会陌生,那么我们今天就从源码角度来说说mybatis的原理,看看它是怎么根据我们定义好的配置操作数据库,首先我们看一下mybatis的使用方式。

 InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");	
 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
 SqlSession sqlSession = sqlSessionFactory.openSession();
 LiveCourseMapper mapper = sqlSession.getMapper(UserMapper.class);	
 List<LiveCourse> userList = mapper.getUserList();

这里我们只能猜出个一二,即通过配置文件构造SqlSession,通过SqlSession操作数据库

2.框架流程图

3.源码解析

3.1、Mapper解析

XMLMapperBuilder的configurationElement方法用来解析mapper,这里协助的类有MapperBuilderAssistant、CacheRefResolver、ResultMapResolver,个人觉得这里的Resolver完全是多次一举,Resolver最后还是通过MapperBuilderAssistant实现

private void configurationElement(XNode context) {
    try {
        //解析namespace属性
        String namespace = context.getStringAttribute("namespace");
        if (namespace.equals("")) {
            throw new BuilderException("Mapper's namespace cannot be empty");
        }
        //设置命名空间
        builderAssistant.setCurrentNamespace(namespace);
        //将此命名空间关联namespace属性指定的命名空间,并设置为当前cache
        cacheRefElement(context.evalNode("cache-ref"));
        //构造cache添加到configuration,并设置为当前cache
        cacheElement(context.evalNode("cache"));
        //构造ParameterMap添加到configuration
        parameterMapElement(context.evalNodes("/mapper/parameterMap"));
        //构造ResultMap添加到configuration
        resultMapElements(context.evalNodes("/mapper/resultMap"));
        //识别sql并缓存,缓存id带有命名空间
        sqlElement(context.evalNodes("/mapper/sql"));
        //构造MappedStatement添加到configuration
        buildStatementFromContext(context.evalNodes("select|insert|update|delete"));
    } catch (Exception e) {
        throw new BuilderException("Error parsing Mapper XML. Cause: " + e, e);
    }
}

MapperBuilderAssistant是XMLMapperBuilder解析的协助类,一般是XMLMapperBuilder读取各个节点的属性和子节点,然后通过MapperBuilderAssistant创建不同的对象

public class MapperBuilderAssistant extends BaseBuilder {
    //当前命名空间,mapper标签的namespace属性
    private String currentNamespace;
    //资源路径
    private String resource;
    //当前缓存
    private Cache currentCache;
    //缓存引用解决标志,解析cache-ref使用
    private boolean unresolvedCacheRef;
    //获取namespace对应的cache设置到currentCache,解析cache-ref使用
    public Cache useCacheRef(String namespace)
    //构造cache设置到currentCache并添加到configuration,解析cache使用
    public Cache useNewCache()
    //构造ParameterMap并添加到configuration,使用build模式,解析parameterMap使用
    public ParameterMap addParameterMap()
    //构造ParameterMapping,使用build模式,解析parameterMap使用
    public ParameterMapping buildParameterMapping()
    //构造ResultMap并添加到configuration,使用build模式,解析resultMap使用
    public ResultMap addResultMap()
    //构造Discriminator,使用build模式,解析resultMap使用
    public Discriminator buildDiscriminator()
    //构造ResultMapping,使用build模式,解析resultMap使用
    public ResultMapping buildResultMapping()
    //构造MappedStatement并添加到configuration,使用build模式,解析select|insert|update|delete使用
    public MappedStatement addMappedStatement()
    //设置MappedStatement.Builder的cache,解析select|insert|update|delete使用
    private void setStatementCache()
    //设置MappedStatement.Builder的parameterMap,解析select|insert|update|delete使用
    private void setStatementParameterMap()
    //设置MappedStatement.Builder的resultMaps(多个)和resultSetType,解析select|insert|update|delete使用
    private void setStatementResultMap()
    //设置MappedStatement.Builder的timeout,解析select|insert|update|delete使用
    private void setStatementTimeout()
    //解决result的java类型
    private Class<?> resolveResultJavaType()
    //解决parameter的java类型
    private Class<?> resolveParameterJavaType()
}

XMLMapperBuilder解析select|insert|update|delete节点时,由于解析过于复杂,这里解析属性和子节点是通过XMLStatementBuilder来实现

public class XMLStatementBuilder extends BaseBuilder {
    //mapper解析助手
    private MapperBuilderAssistant builderAssistant;
    //当前节点
    private XNode context;
    //配置的databaseId
    private String requiredDatabaseId;
    //
    public void parseStatementNode
    public void parseStatementNode() {
        //获取当前节点上的属性
        Integer fetchSize = context.getIntAttribute("fetchSize");
        Integer timeout = context.getIntAttribute("timeout");
        String parameterMap = context.getStringAttribute("parameterMap");
        String parameterType = context.getStringAttribute("parameterType");
        Class<?> parameterTypeClass = resolveClass(parameterType);
        String resultMap = context.getStringAttribute("resultMap");
        String resultType = context.getStringAttribute("resultType");
        String lang = context.getStringAttribute("lang");
        LanguageDriver langDriver = getLanguageDriver(lang);
        //解析resultType对应的class
        Class<?> resultTypeClass = resolveClass(resultType);
        String resultSetType = context.getStringAttribute("resultSetType");
        StatementType statementType = StatementType.valueOf(context.getStringAttribute("statementType", StatementType.PREPARED.toString()));
        //解析resultSetType对应的实例
        ResultSetType resultSetTypeEnum = resolveResultSetType(resultSetType);
        
        String nodeName = context.getNode().getNodeName();
        SqlCommandType sqlCommandType = SqlCommandType.valueOf(nodeName.toUpperCase(Locale.ENGLISH));
        boolean isSelect = sqlCommandType == SqlCommandType.SELECT;
        //非查询是否刷新缓存
        boolean flushCache = context.getBooleanAttribute("flushCache", !isSelect);
        //查询是否使用缓存
        boolean useCache = context.getBooleanAttribute("useCache", isSelect);
        boolean resultOrdered = context.getBooleanAttribute("resultOrdered", false);
        //解析include标签,用实际sql替换include标签
        XMLIncludeTransformer includeParser = new XMLIncludeTransformer(configuration, builderAssistant);
        includeParser.applyIncludes(context.getNode());
        //解析selectKey,同时创建MappedStatement
        processSelectKeyNodes(id, parameterTypeClass, langDriver);
        //解析sql生成SqlSource
        SqlSource sqlSource = langDriver.createSqlSource(configuration, context, parameterTypeClass);
        //获取其余的属性
        String resultSets = context.getStringAttribute("resultSets");
        String keyProperty = context.getStringAttribute("keyProperty");
        String keyColumn = context.getStringAttribute("keyColumn");
        KeyGenerator keyGenerator;
        String keyStatementId = id + SelectKeyGenerator.SELECT_KEY_SUFFIX;
        keyStatementId = builderAssistant.applyCurrentNamespace(keyStatementId, true);
        //如果定义了主键生成器则获取否则初始化主键生成器,后面学习一下KeyGenerator
        if (configuration.hasKeyGenerator(keyStatementId)) {
            keyGenerator = configuration.getKeyGenerator(keyStatementId);
        } else {
            keyGenerator = context.getBooleanAttribute("useGeneratedKeys",
              configuration.isUseGeneratedKeys() && SqlCommandType.INSERT.equals(sqlCommandType))
              ? new Jdbc3KeyGenerator() : new NoKeyGenerator();
        }
        //构造MappedStatement并添加到configuration,使用build模式
        builderAssistant.addMappedStatement(id, sqlSource, statementType, sqlCommandType,
        fetchSize, timeout, parameterMap, parameterTypeClass, resultMap, resultTypeClass,
        resultSetTypeEnum, flushCache, useCache, resultOrdered, 
        keyGenerator, keyProperty, keyColumn, databaseId, langDriver, resultSets);
    }
}

这里解析SqlSource用了LanguageDriver,XMLLanguageDriver是LanguageDriver默认实现类,解析成SqlSource是为了获取BoundSql,SqlSource只有唯一的方法getBoundSql,BoundSql是为后面StatementHandler使用

//解析XNode生成SqlSource
public SqlSource createSqlSource(Configuration configuration, XNode script, Class<?> parameterType) {
    XMLScriptBuilder builder = new XMLScriptBuilder(configuration, script, parameterType);
    return builder.parseScriptNode();
}

LanguageDriver还是通过XMLScriptBuilder实现SqlSource解析;DynamicSqlSource和RawSqlSource区别是动态sql和静态sql之分,DynamicSqlSource需要参数解析,而RawSqlSource不需要参数解析,所以DynamicSqlSource包含了SqlNode,而RawSqlSource包含了SqlSource,这里的SqlSource不是自身,而是StaticSqlSource,在后面我们会细讲

public class XMLScriptBuilder extends BaseBuilder {
    //解析的XNode
    private XNode context;
    //是否动态sql,解析的时候初始化
    private boolean isDynamic;
    //参数类型
    private Class<?> parameterType;
    //解析XNode生成SqlSource,步骤是解析成SqlNode,然后合成MixedSqlNode,再生成SqlSource
    public SqlSource parseScriptNode(){
        //解析XNode生成List<SqlNode>
        List<SqlNode> contents = parseDynamicTags(context);
        //根据List<SqlNode>生成MixedSqlNode
        MixedSqlNode rootSqlNode = new MixedSqlNode(contents);
        SqlSource sqlSource = null;
        if (isDynamic) {
            //如果是动态sql生成DynamicSqlSource
            sqlSource = new DynamicSqlSource(configuration, rootSqlNode);
        } else {
            //如果是静态sql生成RawSqlSource
            sqlSource = new RawSqlSource(configuration, rootSqlNode, parameterType);
        }
        return sqlSource;
    }
    //解析XNode生成SqlNode
    private List<SqlNode> parseDynamicTags(XNode node) {
        List<SqlNode> contents = new ArrayList<SqlNode>();
        NodeList children = node.getNode().getChildNodes();
        for (int i = 0; i < children.getLength(); i++) {
        XNode child = node.newXNode(children.item(i));
        //如果node类型是CDATA或者text
        if (child.getNode().getNodeType() == Node.CDATA_SECTION_NODE || child.getNode().getNodeType() == Node.TEXT_NODE) {
            String data = child.getStringBody("");
            //获取CDATA或者text类型node的主体
            TextSqlNode textSqlNode = new TextSqlNode(data);
            //判断是否是动态sql并创建StaticTextSqlNode、TextSqlNode
            if (textSqlNode.isDynamic()) {
                contents.add(textSqlNode);
                isDynamic = true;
            } else {
                contents.add(new StaticTextSqlNode(data));
            }
        } else if (child.getNode().getNodeType() == Node.ELEMENT_NODE) { // issue #628
            //获取节点名称和节点的处理器
            String nodeName = child.getNode().getNodeName();
            NodeHandler handler = nodeHandlers.get(nodeName);
            if (handler == null) {
                throw new BuilderException("Unknown element <" + nodeName + "> in SQL statement.");
            }
            //使用节点处理器生成不同的SqlNode
            handler.handleNode(child, contents);
            isDynamic = true;
        }
        }
        return contents;
    }
    //生成SqlNode
    private interface NodeHandler
    //生成VarDeclSqlNode
    private class BindHandler implements NodeHandler
    //生成TrimHandler
    private class TrimHandler implements NodeHandler
    //生成WhereHandler
    private class WhereHandler implements NodeHandler
    //生成SetSqlNode
    private class SetHandler implements NodeHandler
    //生成ForEachSqlNode
    private class ForEachHandler implements NodeHandler
    //生成IfHandler
    private class IfHandler implements NodeHandler
    //生成MixedSqlNode
    private class OtherwiseHandler implements NodeHandler
    //生成ChooseSqlNode
    private class ChooseHandler implements NodeHandler
}

3.2、SQLNode解析

SqlNode是解析select|insert|update|delete后的sql对象,每个非文本节点包含了子节点SqlNode,文本节点包含sql文本,每个节点都包含了apply方法,这是运行时获取Sql使用

//TextSqlNode用来解析SQL文本节点,这里使用GenericTokenParser检测\${},DynamicCheckerTokenParser检测当前SQL文本节点是不是动态sql,BindingTokenParser找到实际值并替换
public class TextSqlNode implements SqlNode {
    //sql文本
    private String text;

    public TextSqlNode(String text) {
        this.text = text;
    }
    //校验是否是动态sql
    public boolean isDynamic(){
        //动态sql检验TokenHandler
        DynamicCheckerTokenParser checker = new DynamicCheckerTokenParser();
        //使用TokenHandler创建GenericTokenParser
        GenericTokenParser parser = createParser(checker);
        //如果是动态sql,DynamicCheckerTokenParser会修改属性isDynamic
        parser.parse(text);
        return checker.isDynamic();
    }
    //获取sql添加到context
    public boolean apply(DynamicContext context) {
        //使用BindingTokenParser创建GenericTokenParser
        GenericTokenParser parser = createParser(new BindingTokenParser(context));
        //获取sql添加到context
        context.appendSql(parser.parse(text));
        return true;
    }
    //创建GenericTokenParser
    private GenericTokenParser createParser(TokenHandler handler) {
        return new GenericTokenParser("${", "}", handler);
    }
}
  
//StaticTextSqlNode用来解析SQL文本节点,但是不包含${}
public class StaticTextSqlNode implements SqlNode {
    //sql文本
    private String text;

    public StaticTextSqlNode(String text) {
        this.text = text;
    }
    //获取sql添加到context
    public boolean apply(DynamicContext context) {
        context.appendSql(text);
        return true;
    }
}

//VarDeclSqlNode用来解析bind节点,主要用来绑定变量
public class VarDeclSqlNode implements SqlNode {
    //上下文的变量名
    private final String name;
    //OGNL表达式
    private final String expression;

    public VarDeclSqlNode(String var, String exp) {
        name = var;
        expression = exp;
    }

    public boolean apply(DynamicContext context) {
        final Object value = OgnlCache.getValue(expression, context.getBindings());
        //将值绑定到上下文
        context.bind(name, value);
        return true;
    }
}

//TrimSqlNode用来解析trim节点,主要用来在sql首尾添加字符和删除字符
public class TrimSqlNode implements SqlNode {
    //包含的SqlNode
    private SqlNode contents;
    //前缀
    private String prefix;
    //后缀
    private String suffix;
    //sql开头遇到这些字符需要替换为空
    private List<String> prefixesToOverride;
    //sql结尾遇到这些字符需要替换为空
    private List<String> suffixesToOverride;
    private Configuration configuration;
    //获取sql添加到context
    public boolean apply(DynamicContext context) {
        //使用FilteredDynamicContext代理DynamicContext
        FilteredDynamicContext filteredDynamicContext = new FilteredDynamicContext(context);
        //获取sql添加到FilteredDynamicContext
        boolean result = contents.apply(filteredDynamicContext);
        //获取sql添加到DynamicContext
        filteredDynamicContext.applyAll();
        return result;
    }
    //将|连接的字符串分割成数组
    private static List<String> parseOverrides(String overrides)
    private class FilteredDynamicContext{
        //代理的DynamicContext 
        private DynamicContext delegate;
        //prefix是否添加
        private boolean prefixApplied;
        //suffix是否添加
        private boolean suffixApplied;
        //临时存储sql
        private StringBuilder sqlBuffer;
        //重写父类的appendSql,临时存储sql在sqlBuffer
        @Override
        public void appendSql(String sql) {
          sqlBuffer.append(sql);
        }
        //如果sqlBuffer不空,则使用applyPrefix、applySuffix修改sqlBuffer,再修改代理的DynamicContext 
        public void applyAll() {
            sqlBuffer = new StringBuilder(sqlBuffer.toString().trim());
            String trimmedUppercaseSql = sqlBuffer.toString().toUpperCase(Locale.ENGLISH);
            if (trimmedUppercaseSql.length() > 0) {
                applyPrefix(sqlBuffer, trimmedUppercaseSql);
                applySuffix(sqlBuffer, trimmedUppercaseSql);
            }
            delegate.appendSql(sqlBuffer.toString());
        }
    }
}

//WhereSqlNode用来解析where节点,在sql首部添加where和首部删除and、or
public class WhereSqlNode extends TrimSqlNode {
    private static List<String> prefixList = Arrays.asList("AND ","OR ","AND\n", "OR\n", "AND\r", "OR\r", "AND\t", "OR\t");
    //其实就是TrimSqlNode,添加where,去掉开头的and、or关键字
    public WhereSqlNode(Configuration configuration, SqlNode contents) {
        super(configuration, contents, "WHERE", prefixList, null, null);
    }
}

//SetSqlNode用来解析set节点,在sql首部添加set和尾部删除,
public class SetSqlNode extends TrimSqlNode {
    private static List<String> suffixList = Arrays.asList(",");
    //其实就是TrimSqlNode,添加set,去掉尾部的,
    public SetSqlNode(Configuration configuration,SqlNode contents) {
        super(configuration, contents, "SET", null, null, suffixList);
    }
}

//ForEachSqlNode用来解析foreach节点,来遍历集合
public class ForEachSqlNode implements SqlNode {
    public static final String ITEM_PREFIX = "__frch_";
    private ExpressionEvaluator evaluator;
    //集合
    private String collectionExpression;
    //包含的SqlNode
    private SqlNode contents;
    //开头添加的字符串
    private String open;
    //结尾添加的字符串
    private String close;
    //分割符
    private String separator;
    //集合项
    private String item;
    //索引
    private String index;
    private Configuration configuration;
    public boolean apply(DynamicContext context) {
        //添加open
        applyOpen(context);
        int i = 0;
        //对集合对象遍历
        for (Object o : iterable) {
            //备份context
            DynamicContext oldContext = context;
            if (first) {
                //第一个不需要添加前缀
                context = new PrefixedContext(context, "");
            } else {
                if (separator != null) {
                    //当separator不空且非第一个时需要添加前缀,
                    context = new PrefixedContext(context, separator);
                } else {
                    context = new PrefixedContext(context, "");
                }
            }
            //生成序列号
            int uniqueNumber = context.getUniqueNumber();
            //将index和i关联,item和o关联
            if (o instanceof Map.Entry) { // Issue #709 
                @SuppressWarnings("unchecked") 
                Map.Entry<Object, Object> mapEntry = (Map.Entry<Object, Object>) o;
                applyIndex(context, mapEntry.getKey(), uniqueNumber);
                applyItem(context, mapEntry.getValue(), uniqueNumber);
            } else {
                applyIndex(context, i, uniqueNumber);
                applyItem(context, o, uniqueNumber);
            }
            //FilteredDynamicContext替换其中的index和item,将sql添加到context
            contents.apply(new FilteredDynamicContext(configuration, context, index, item, uniqueNumber));
            //如果PrefixedContext的prefixApplied为true说明添加了前缀,这时first就为false
            if (first) first = !((PrefixedContext) context).isPrefixApplied();
            //还原 context
            context = oldContext;
            i++;
        }
        //添加colse
        applyClose(context);
        return true;
    }
    public FilteredDynamicContext(Configuration configuration,DynamicContext delegate, String itemIndex, String item, int i) {
        super(configuration, null);
        //代理的DynamicContext
        this.delegate = delegate;
        //顺序
        this.index = i;
        //foreach的index
        this.itemIndex = itemIndex;
        //foreach的item
        this.item = item;
    }
    
    @Override
    public Map<String, Object> getBindings() {
        return delegate.getBindings();
    }
    
    @Override
    public void bind(String name, Object value) {
        delegate.bind(name, value);
    }
    
    @Override
    public String getSql() {
        return delegate.getSql();
    }
    
    @Override
    public void appendSql(String sql) {
    GenericTokenParser parser = new GenericTokenParser("#{", "}", new TokenHandler() {
      public String handleToken(String content) {
        //替换foreach的item
        String newContent = content.replaceFirst("^\\s*" + item + "(?![^.,:\\s])", itemizeItem(item, index));
        if (itemIndex != null && newContent.equals(content)) {
            //替换foreach的index
          newContent = content.replaceFirst("^\\s*" + itemIndex + "(?![^.,:\\s])", itemizeItem(itemIndex, index));
        }
        return new StringBuilder("#{").append(newContent).append("}").toString();
      }
    });
    
    delegate.appendSql(parser.parse(sql));
    }
    
    @Override
    public int getUniqueNumber() {
        return delegate.getUniqueNumber();
    }
}

//IfSqlNode用来解析if节点
public class IfSqlNode implements SqlNode {
    private ExpressionEvaluator evaluator;
    //test的表达式
    private String test;
    //包含的SqlNode 
    private SqlNode contents;
    
    public IfSqlNode(SqlNode contents, String test) {
        this.test = test;
        this.contents = contents;
        this.evaluator = new ExpressionEvaluator();
    }
    
    public boolean apply(DynamicContext context) {
        if (evaluator.evaluateBoolean(test, context.getBindings())) {
            //test判断正确,则添加sql到context
            contents.apply(context);
            return true;
        }
        return false;
    }
}

//ChooseSqlNode用来解析choose节点
public class ChooseSqlNode implements SqlNode {
    //default的SqlNode 
    private SqlNode defaultSqlNode;
    //when的SqlNode
    private List<SqlNode> ifSqlNodes;
    
    public ChooseSqlNode(List<SqlNode> ifSqlNodes, SqlNode defaultSqlNode) {
        this.ifSqlNodes = ifSqlNodes;
        this.defaultSqlNode = defaultSqlNode;
    }
    
    public boolean apply(DynamicContext context) {
        for (SqlNode sqlNode : ifSqlNodes) {
            //如果if的SqlNode添加成功则返回
          if (sqlNode.apply(context)) {
            return true;
          }
        }
        if (defaultSqlNode != null) {
            //否则默认的SqlNode添加成功返回
          defaultSqlNode.apply(context);
          return true;
        }
        return false;
    }
}

3.3、获取SqlSession

SqlSessionFactory获取SqlSession,DefaultSqlSessionFactory是SqlSessionFactory默认实现类

//SqlSession工厂
public interface SqlSessionFactory {
    SqlSession openSession;
    Configuration getConfiguration();
}

public class DefaultSqlSessionFactory implements SqlSessionFactory {
    private final Configuration configuration;
    //通过数据源创建SqlSession
    private SqlSession openSessionFromDataSource(ExecutorType execType, 
    TransactionIsolationLevel level, boolean autoCommit) {
        Transaction tx = null;
        try {
            //获取当前执行环境,这里面有TransactionFactory和DataSource
            final Environment environment = configuration.getEnvironment();
            //获取配置的TransactionFactory,一般是JDBC
            final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
            //使用TransactionFactory创建Transaction,需要DataSource,事务隔离级别,是否事务
            tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
            //根据ExecutorType和Transaction创建最重要的Executor,即执行器
            final Executor executor = configuration.newExecutor(tx, execType);
            //创建DefaultSqlSession,包含了configuration、executor
            return new DefaultSqlSession(configuration, executor, autoCommit);
        } catch (Exception e) {
            closeTransaction(tx); // may have fetched a connection so lets call close()
            throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);
        } finally {
            ErrorContext.instance().reset();
        }
   }
    //通过数据库连接Connection创建SqlSession
    private SqlSession openSessionFromConnection(ExecutorType execType, 
    Connection connection) {
        try {
            boolean autoCommit;
            try {
                autoCommit = connection.getAutoCommit();
            } catch (SQLException e) {
                // Failover to true, as most poor drivers
                // or databases won't support transactions
                autoCommit = true;
            }      
            final Environment environment = configuration.getEnvironment();
            final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
            //使用TransactionFactory创建Transaction,需要Connection
            final Transaction tx = transactionFactory.newTransaction(connection);
            //根据ExecutorType和Transaction创建最重要的Executor,即执行器
            final Executor executor = configuration.newExecutor(tx, execType);
            //创建DefaultSqlSession,包含了configuration、executor
            return new DefaultSqlSession(configuration, executor, autoCommit);
        } catch (Exception e) {
            throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);
        } finally {
            ErrorContext.instance().reset();
        }
    }

private TransactionFactory getTransactionFactoryFromEnvironment(Environment environment) {
    if (environment == null || environment.getTransactionFactory() == null) {
        return new ManagedTransactionFactory();
    }
    return environment.getTransactionFactory();
}

    private void closeTransaction(Transaction tx) {
        if (tx != null) {
            try {
              tx.close();
            } catch (SQLException ignore) {
              // Intentionally ignore. Prefer previous error.
            }
        }
    }
}

3.4、获取mapper

DefaultSqlSession获取mapper,调用configuration的getMapper,调用mapperRegistry的getMapper

public class MapperRegistry {
    private Configuration config;
    private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap<Class<?>, MapperProxyFactory<?>>();
    public MapperRegistry(Configuration config) {
        this.config = config;
    }
    @SuppressWarnings("unchecked")
    public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
        //获取type对应的MapperProxyFactory,这个是在解析时创建的
        final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
        if (mapperProxyFactory == null)
            throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
        try {
            //使用MapperProxyFactory创建type实例
            return mapperProxyFactory.newInstance(sqlSession);
        } catch (Exception e) {
            throw new BindingException("Error getting mapper instance. Cause: " + e, e);
        }
    }
    //判断是否存在type对应的MapperProxyFactory
    public <T> boolean hasMapper(Class<T> type) {
        return knownMappers.containsKey(type);
    }
    //添加type对应的MapperProxyFactory
    public <T> void addMapper(Class<T> type) {
        if (type.isInterface()) {
            if (hasMapper(type)) {
                throw new BindingException("Type " + type + " is already known to the MapperRegistry.");
            }
            boolean loadCompleted = false;
            try {
                knownMappers.put(type, new MapperProxyFactory<T>(type));
                // It's important that the type is added before the parser is run
                // otherwise the binding may automatically be attempted by the
                // mapper parser. If the type is already known, it won't try.
                MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type);
                parser.parse();
                loadCompleted = true;
            } finally {
                if (!loadCompleted) {
                    knownMappers.remove(type);
                }
            }
        }
    }
}

public class MapperProxyFactory<T> {
    //mapper的class
    private final Class<T> mapperInterface;
    //MapperMethod缓存
    private Map<Method, MapperMethod> methodCache = new ConcurrentHashMap<Method, MapperMethod>();
    
    @SuppressWarnings("unchecked")
    protected T newInstance(MapperProxy<T> mapperProxy) {
        //使用jdk动态代理生成mapper代理类
        return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
    }
    
    public T newInstance(SqlSession sqlSession) {
        //创建mapperProxy
        final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
        return newInstance(mapperProxy);
    }
}

public class MapperProxy<T> implements InvocationHandler, Serializable {

    private static final long serialVersionUID = -6424540398559729838L;
    private final SqlSession sqlSession;
    //mapper的class
    private final Class<T> mapperInterface;
    //MapperMethod缓存
    private final Map<Method, MapperMethod> methodCache;
    
    public MapperProxy(SqlSession sqlSession, Class<T> mapperInterface, Map<Method, MapperMethod> methodCache) {
        this.sqlSession = sqlSession;
        this.mapperInterface = mapperInterface;
        this.methodCache = methodCache;
    }
    
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //如果调用方法类是对象,则直接调用对象的方法
        if (Object.class.equals(method.getDeclaringClass())) {
            try {
                return method.invoke(this, args);
            } catch (Throwable t) {
                throw ExceptionUtil.unwrapThrowable(t);
            }
        }
        //调用MapperMethod的方法
        final MapperMethod mapperMethod = cachedMapperMethod(method);
        return mapperMethod.execute(sqlSession, args);
    }
    
    private MapperMethod cachedMapperMethod(Method method) {
        MapperMethod mapperMethod = methodCache.get(method);
        if (mapperMethod == null) {
            mapperMethod = new MapperMethod(mapperInterface, method, sqlSession.getConfiguration());
            methodCache.put(method, mapperMethod);
        }
        return mapperMethod;
    }
}

public class MapperMethod {
    //方法id和sql类型组合对象
    private final SqlCommand command;
    //方法签名,包含返回类型、是否void、是否集合、返回map、mapkey,参数是否named,RowBounds的index,ResultHandler的index,参数名map
    private final MethodSignature method;
    public Object execute(SqlSession sqlSession, Object[] args) {
        Object result;
        //如果插入
        if (SqlCommandType.INSERT == command.getType()) {
            //将形参转换成对象
            Object param = method.convertArgsToSqlCommandParam(args);
            //调用sqlSession.insert
            result = rowCountResult(sqlSession.insert(command.getName(), param));
        } else if (SqlCommandType.UPDATE == command.getType()) {
            //将形参转换成对象
            Object param = method.convertArgsToSqlCommandParam(args);
            //调用sqlSession.update
            result = rowCountResult(sqlSession.update(command.getName(), param));
        } else if (SqlCommandType.DELETE == command.getType()) {
            //将形参转换成对象
            Object param = method.convertArgsToSqlCommandParam(args);
            //调用sqlSession.delete
            result = rowCountResult(sqlSession.delete(command.getName(), param));
        } else if (SqlCommandType.SELECT == command.getType()) {
            //方法返回void并且参数有ResultHandler实例
            if (method.returnsVoid() && method.hasResultHandler()) {
            //executeWithResultHandler调用sqlSession.select参数中有ResultHandler实例
            executeWithResultHandler(sqlSession, args);
            result = null;
        } else if (method.returnsMany()) {
            //executeForMany调用sqlSession.<E>selectList
            result = executeForMany(sqlSession, args);
        } else if (method.returnsMap()) {
            //executeForMap调用sqlSession.<K, V>selectMap
            result = executeForMap(sqlSession, args);
        } else {
            //调用sqlSession.selectOne
            Object param = method.convertArgsToSqlCommandParam(args);
            result = sqlSession.selectOne(command.getName(), param);
        }
        } else {
            throw new BindingException("Unknown execution method for: " + command.getName());
        }
        if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) {
            throw new BindingException("Mapper method '" + command.getName() 
            + " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ").");
        }
        return result;
    }
    //根据方法签名返回类型和rowCount设置返回值
    private Object rowCountResult(int rowCount)
    //将参数转换成对象,如果参数中有RowBounds实例,则带上RowBounds实例,从参数中获取ResultHandler实例,调用sqlSession.select
    private void executeWithResultHandler()
    //将参数转换成对象,如果参数中有RowBounds实例,则带上RowBounds实例,调用sqlSession.<E>selectList
    private <E> Object executeForMany()
    //将参数转换成对象,如果参数中有RowBounds实例,则带上RowBounds实例,获取mapkey,调用sqlSession.<K, V>selectMap
    private <K, V> Map<K, V> executeForMap()
    //多个参数封装对象
    public static class ParamMap<V>  extends HashMap<String, V> {}
    //sql类型和方法名称封装
    public static class SqlCommand {
        //方法id,包含命名空间
        private final String name;
        //sql类型
        private final SqlCommandType type;
    
        public SqlCommand(Configuration configuration, Class<?> mapperInterface, Method method) throws BindingException {
            //构造statementName
            String statementName = mapperInterface.getName() + "." + method.getName();
            MappedStatement ms = null;
            //获取MappedStatement
            if (configuration.hasStatement(statementName)) {
                ms = configuration.getMappedStatement(statementName);
            } else if (!mapperInterface.equals(method.getDeclaringClass().getName())) { // issue #35
                String parentStatementName = method.getDeclaringClass().getName() + "." + method.getName();
                if (configuration.hasStatement(parentStatementName)) {
                    ms = configuration.getMappedStatement(parentStatementName);
                }
            }
            if (ms == null) {
                throw new BindingException("Invalid bound statement (not found): " + statementName);
            }
            name = ms.getId();
            type = ms.getSqlCommandType();
            if (type == SqlCommandType.UNKNOWN) {
                throw new BindingException("Unknown execution method for: " + name);
            }
        }
    }
public static class MethodSignature {
  //方法是否返回集合
  private final boolean returnsMany;
  //方法是否返回map
  private final boolean returnsMap;
  //方法是否返回void
  private final boolean returnsVoid;
  //方法返回类型
  private final Class<?> returnType;
  //返回map指定的key
  private final String mapKey;
  //参数中ResultHandler实例的index
  private final Integer resultHandlerIndex;
  //参数中RowBounds实例的index
  private final Integer rowBoundsIndex;
  //参数别名
  private final SortedMap<Integer, String> params;
  //是否有named参数
  private final boolean hasNamedParameters;

  public MethodSignature(Configuration configuration, Method method) throws BindingException {
    this.returnType = method.getReturnType();
    this.returnsVoid = void.class.equals(this.returnType);
    this.returnsMany = (configuration.getObjectFactory().isCollection(this.returnType) || this.returnType.isArray());
    this.mapKey = getMapKey(method);
    this.returnsMap = (this.mapKey != null);
    this.hasNamedParameters = hasNamedParams(method);
    //获取RowBounds类型参数下标,如果有多个,则用第一个
    this.rowBoundsIndex = getUniqueParamIndex(method, RowBounds.class);
    this.resultHandlerIndex = getUniqueParamIndex(method, ResultHandler.class);
    //遍历方法定义参数,key是方法参数下标,value是别名,从0开始,如果使用param注解,则替换成param注解指定的name
    this.params = Collections.unmodifiableSortedMap(getParams(method, this.hasNamedParameters));
  }

  public Object convertArgsToSqlCommandParam(Object[] args) {
    final int paramCount = params.size();
    if (args == null || paramCount == 0) {
      //形参是null或者方法参数个数是0直接返回null
      return null;
    } else if (!hasNamedParameters && paramCount == 1) {
      //参数个数是1,并且没有别名
      return args[params.keySet().iterator().next()];
    } else {
      final Map<String, Object> param = new ParamMap<Object>();
      int i = 0;
      //这里构造参数的时候使用了两个定义,一个是0,1,2...,一个是param1,param2
      for (Map.Entry<Integer, String> entry : params.entrySet()) {
        param.put(entry.getValue(), args[entry.getKey()]);
        // issue #71, add param names as param1, param2...but ensure backward compatibility
        final String genericParamName = "param" + String.valueOf(i + 1);
        if (!param.containsKey(genericParamName)) {
          param.put(genericParamName, args[entry.getKey()]);
        }
        i++;
      }
      return param;
    }
  }
  //获取方法参数类型和paramType相同的参数下标
  private Integer getUniqueParamIndex(Method method, Class<?> paramType)
  //获取方法返回类型是map时方法注解MapKey的value
  private String getMapKey(Method method)
  //获取方法参数下标和别名map,别名是从0开始,有Param注解则用注解指定的别名
  private SortedMap<Integer, String> getParams(Method method, boolean hasNamedParameters) {
    final SortedMap<Integer, String> params = new TreeMap<Integer, String>();
    final Class<?>[] argTypes = method.getParameterTypes();
    for (int i = 0; i < argTypes.length; i++) {
      if (!RowBounds.class.isAssignableFrom(argTypes[i]) && !ResultHandler.class.isAssignableFrom(argTypes[i])) {
        String paramName = String.valueOf(params.size());
        if (hasNamedParameters) {
          paramName = getParamNameFromAnnotation(method, i, paramName);
        }
        params.put(i, paramName);
      }
    }
    return params;
  }
  //获取Param注解指定的值
  private String getParamNameFromAnnotation(Method method, int i, String paramName) {
    final Object[] paramAnnos = method.getParameterAnnotations()[i];
    for (Object paramAnno : paramAnnos) {
      if (paramAnno instanceof Param) {
        paramName = ((Param) paramAnno).value();
      }
    }
    return paramName;
  }
  //方法是否有指定的参数
  private boolean hasNamedParams(Method method) {
    boolean hasNamedParams = false;
    final Object[][] paramAnnos = method.getParameterAnnotations();
    for (Object[] paramAnno : paramAnnos) {
      for (Object aParamAnno : paramAnno) {
        if (aParamAnno instanceof Param) {
          hasNamedParams = true;
          break;
        }
      }
    }
    return hasNamedParams;
  }
}
}

3.5、DefaultSqlSession执行sql

DefaultSqlSession执行sql,select、update、insert、delete、commit、rollback

public class DefaultSqlSession implements SqlSession {
  //configuration
  private Configuration configuration;
  //执行器
  private Executor executor;
  //自动提交
  private boolean autoCommit;
  private boolean dirty;
  
  public DefaultSqlSession(Configuration configuration, Executor executor, boolean autoCommit) {
    this.configuration = configuration;
    this.executor = executor;
    this.dirty = false;
    this.autoCommit = autoCommit;
  }

  public DefaultSqlSession(Configuration configuration, Executor executor) {
    this(configuration, executor, false);
  }
  //查询一条数据
  public <T> T selectOne(String statement) {
  return this.<T>selectOne(statement, null);
  }
  //带参数查询一条数据
  public <T> T selectOne(String statement, Object parameter) {
  // Popular vote was to return null on 0 results and throw exception on too many.
  //调用selectList
  List<T> list = this.<T>selectList(statement, parameter);
  if (list.size() == 1) {
    return list.get(0);
  } else if (list.size() > 1) {
    throw new TooManyResultsException("Expected one result (or null) to be returned by selectOne(), but found: " + list.size());
  } else {
    return null;
  }
}
//查询map
public <K, V> Map<K, V> selectMap(String statement, String mapKey) {
  return this.selectMap(statement, null, mapKey, RowBounds.DEFAULT);
}
//带参数查询map
public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey) {
  return this.selectMap(statement, parameter, mapKey, RowBounds.DEFAULT);
}
   //带参数和RowBounds查询map
public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds) {
  final List<?> list = selectList(statement, parameter, rowBounds);
  //创建ResultHandler
  final DefaultMapResultHandler<K, V> mapResultHandler = new DefaultMapResultHandler<K, V>(mapKey,
      configuration.getObjectFactory(), configuration.getObjectWrapperFactory());
  final DefaultResultContext context = new DefaultResultContext();
  for (Object o : list) {
    context.nextResultObject(o);
    mapResultHandler.handleResult(context);
  }
  Map<K, V> selectedMap = mapResultHandler.getMappedResults();
  return selectedMap;
}
//查询多条数据
public <E> List<E> selectList(String statement) {
  return this.selectList(statement, null);
}
//带参数查询多条数据
public <E> List<E> selectList(String statement, Object parameter) {
  return this.selectList(statement, parameter, RowBounds.DEFAULT);
}
//带参数和RowBounds查询多条数据
public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
  try {
    MappedStatement ms = configuration.getMappedStatement(statement);
    //调用执行器查询
    List<E> result = executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
    return result;
  } catch (Exception e) {
    throw ExceptionFactory.wrapException("Error querying database.  Cause: " + e, e);
  } finally {
    ErrorContext.instance().reset();
  }
}
//带参数和ResultHandler查询
public void select(String statement, Object parameter, ResultHandler handler) {
  select(statement, parameter, RowBounds.DEFAULT, handler);
}
//带ResultHandler查询
public void select(String statement, ResultHandler handler) {
  select(statement, null, RowBounds.DEFAULT, handler);
}
//带参数和RowBounds和ResultHandler查询
public void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler) {
  try {
    MappedStatement ms = configuration.getMappedStatement(statement);
    //调用执行器查询
    executor.query(ms, wrapCollection(parameter), rowBounds, handler);
  } catch (Exception e) {
    throw ExceptionFactory.wrapException("Error querying database.  Cause: " + e, e);
  } finally {
    ErrorContext.instance().reset();
  }
}
//插入
public int insert(String statement) {
  return insert(statement, null);
}
//带参数插入
public int insert(String statement, Object parameter) {
  return update(statement, parameter);
}
//更新
public int update(String statement) {
  return update(statement, null);
}
//带参数更新
public int update(String statement, Object parameter) {
  try {
    dirty = true;
    MappedStatement ms = configuration.getMappedStatement(statement);
    return executor.update(ms, wrapCollection(parameter));
  } catch (Exception e) {
    throw ExceptionFactory.wrapException("Error updating database.  Cause: " + e, e);
  } finally {
    ErrorContext.instance().reset();
  }
}
//删除
public int delete(String statement) {
  return update(statement, null);
}
//带参数删除
public int delete(String statement, Object parameter) {
  return update(statement, parameter);
}
//提交
public void commit() {
  commit(false);
}

public void commit(boolean force) {
  try {
      //调用执行器的commit
    executor.commit(isCommitOrRollbackRequired(force));
    dirty = false;
  } catch (Exception e) {
    throw ExceptionFactory.wrapException("Error committing transaction.  Cause: " + e, e);
  } finally {
    ErrorContext.instance().reset();
  }
}
//回滚
public void rollback() {
  rollback(false);
}

public void rollback(boolean force) {
  try {
      //调用执行器回滚
    executor.rollback(isCommitOrRollbackRequired(force));
    dirty = false;
  } catch (Exception e) {
    throw ExceptionFactory.wrapException("Error rolling back transaction.  Cause: " + e, e);
  } finally {
    ErrorContext.instance().reset();
  }
}
//flush
public List<BatchResult> flushStatements() {
  try {
    //调用执行器flush
    return executor.flushStatements();
  } catch (Exception e) {
    throw ExceptionFactory.wrapException("Error flushing statements.  Cause: " + e, e);
  } finally {
    ErrorContext.instance().reset();
  }
}
//关闭
public void close() {
  try {
    //调用执行器关闭
    executor.close(isCommitOrRollbackRequired(false));
    dirty = false;
  } finally {
    ErrorContext.instance().reset();
  }
}
//获取Configuration 
public Configuration getConfiguration() {
  return configuration;
}
//获取mapper
public <T> T getMapper(Class<T> type) {
  return configuration.<T>getMapper(type, this);
}
//获取连接
public Connection getConnection() {
  try {
    //从执行器的Transaction获取连接
    return executor.getTransaction().getConnection();
  } catch (SQLException e) {
    throw ExceptionFactory.wrapException("Error getting a new connection.  Cause: " + e, e);
  }
}
}

3.6、Executor执行sql

DefaultSqlSession委托Executor实现select、update、insert、delete、commit、rollback

//执行器父类
public abstract class BaseExecutor implements Executor {
    private static final Log log = LogFactory.getLog(BaseExecutor.class);
    //事务
    protected Transaction transaction;
    //自己引用自己
    protected Executor wrapper;
    protected ConcurrentLinkedQueue<DeferredLoad> deferredLoads;
    //本地缓存
    protected PerpetualCache localCache;
    //callable使用的本地缓存
    protected PerpetualCache localOutputParameterCache;
    protected Configuration configuration;
    //查询量
    protected int queryStack = 0;
    //执行器是否关闭
    private boolean closed;
    public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
        ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());
        if (closed) throw new ExecutorException("Executor was closed.");
        //如果查询量是0并且MappedStatement需要刷新缓存
        if (queryStack == 0 && ms.isFlushCacheRequired()) {
            clearLocalCache();
        }
        List<E> list;
        try {
            queryStack++;
            //从本地缓存中获取
            list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;
            if (list != null) {
                //callable从缓存中获取
              handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
            } else {
                //从数据库查询
              list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
            }
        } finally {
            queryStack--;
        }
        if (queryStack == 0) {
            for (DeferredLoad deferredLoad : deferredLoads) {
              deferredLoad.load();
            }
            deferredLoads.clear(); // issue #601
            //如果本地缓存范围是statement,则清除本地缓存
            if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
              clearLocalCache(); // issue #482
            }
        }
        return list;
    }
    //创建CacheKey 
    public CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql)
    //从数据库查询
    private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
        List<E> list;
        localCache.putObject(key, EXECUTION_PLACEHOLDER);
        try {
            list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
        } finally {
            localCache.removeObject(key);
        }
        //设置本地缓存
        localCache.putObject(key, list);
        if (ms.getStatementType() == StatementType.CALLABLE) {
            localOutputParameterCache.putObject(key, parameter);
        }
        return list;
    }
    //MappedStatement是否缓存
    public boolean isCached(MappedStatement ms, CacheKey key)
    //执行器提交
    public void commit(boolean required)
    //执行器回滚
    public void rollback(boolean required)
    //清除本地缓存
    public void clearLocalCache()
}

public class SimpleExecutor extends BaseExecutor {
    public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
        Statement stmt = null;
        try {
        Configuration configuration = ms.getConfiguration();
        //创建StatementHandler 
        StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null);
        //通过StatementHandler获取Statement
        stmt = prepareStatement(handler, ms.getStatementLog());
        //执行StatementHandler的update
        return handler.update(stmt);
        } finally {
        closeStatement(stmt);
        }
    }

    public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
        Statement stmt = null;
        try {
            Configuration configuration = ms.getConfiguration();
            StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
            stmt = prepareStatement(handler, ms.getStatementLog());
            //执行StatementHandler的//执行StatementHandler的update
            return handler.<E>query(stmt, resultHandler);
        } finally {
            closeStatement(stmt);
        }
    }
    //清空statement
    public List<BatchResult> doFlushStatements(boolean isRollback) throws SQLException {
        return Collections.emptyList();
    }
    //返回Statement
    private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
        Statement stmt;
        Connection connection = getConnection(statementLog);
        stmt = handler.prepare(connection);
        handler.parameterize(stmt);
        return stmt;
    }
}

public class ReuseExecutor extends BaseExecutor {
    //Statement缓存
    private final Map<String, Statement> statementMap = new HashMap<String, Statement>();
    //同SimpleRxecutor
    public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
        Configuration configuration = ms.getConfiguration();
        StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null);
        Statement stmt = prepareStatement(handler, ms.getStatementLog());
        return handler.update(stmt);
    }
    //同SimpleExecutor
    public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
        Configuration configuration = ms.getConfiguration();
        StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
        Statement stmt = prepareStatement(handler, ms.getStatementLog());
        return handler.<E>query(stmt, resultHandler);
    }
    //清空statement
    public List<BatchResult> doFlushStatements(boolean isRollback) throws SQLException {
        for (Statement stmt : statementMap.values()) {
            closeStatement(stmt);
        }
        statementMap.clear();
        return Collections.emptyList();
    }
    //区别于SimpleStatement,这里使用了缓存
    private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
        Statement stmt;
        BoundSql boundSql = handler.getBoundSql();
        String sql = boundSql.getSql();
        //sql是否有Statement缓存
        if (hasStatementFor(sql)) {
            //从缓存中获取Statement
            stmt = getStatement(sql);
        } else {
            //获取数据库连接创建Statement
            Connection connection = getConnection(statementLog);
            stmt = handler.prepare(connection);
            putStatement(sql, stmt);
        }
        handler.parameterize(stmt);
        return stmt;
    }
  }
  
  public class BatchExecutor extends BaseExecutor {
    public static final int BATCH_UPDATE_RETURN_VALUE = Integer.MIN_VALUE + 1002;
    //Statement数组
    private final List<Statement> statementList = new ArrayList<Statement>();
    //批处理结果
    private final List<BatchResult> batchResultList = new ArrayList<BatchResult>();
    //当前sql
    private String currentSql;
    //当前MappedStatement 
    private MappedStatement currentStatement;
  
    public int doUpdate(MappedStatement ms, Object parameterObject) throws SQLException {
        final Configuration configuration = ms.getConfiguration();
        final StatementHandler handler = configuration.newStatementHandler(this, ms, parameterObject, RowBounds.DEFAULT, null, null);
        final BoundSql boundSql = handler.getBoundSql();
        final String sql = boundSql.getSql();
        final Statement stmt;
        //如果sql和当前sql相同,MappedStatement也相同
        if (sql.equals(currentSql) && ms.equals(currentStatement)) {
            int last = statementList.size() - 1;
            //取出上一条Statement
            stmt = statementList.get(last);
            //取出上一条批处理结果
            BatchResult batchResult = batchResultList.get(last);
            //将当前参数添加到批处理结果集中
            batchResult.addParameterObject(parameterObject);
        } else {
            //获取一个数据库连接创建Statement
            Connection connection = getConnection(ms.getStatementLog());
            stmt = handler.prepare(connection);
            currentSql = sql;
            currentStatement = ms;
            statementList.add(stmt);
            batchResultList.add(new BatchResult(ms, sql, parameterObject));
        }
        //Statement设置预编译参数
        handler.parameterize(stmt);
        //Statement设置批处理
        handler.batch(stmt);
        return BATCH_UPDATE_RETURN_VALUE;
    }
    public <E> List<E> doQuery(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql)
    throws SQLException {
        Statement stmt = null;
        try {
            //查询之前会清空Statement
            flushStatements();
            Configuration configuration = ms.getConfiguration();
            StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameterObject, rowBounds, resultHandler, boundSql);
            Connection connection = getConnection(ms.getStatementLog());
            stmt = handler.prepare(connection);
            handler.parameterize(stmt);
            return handler.<E>query(stmt, resultHandler);
        } finally {
            closeStatement(stmt);
        }
    }
    public List<BatchResult> doFlushStatements(boolean isRollback) throws SQLException {
        try {
        List<BatchResult> results = new ArrayList<BatchResult>();
        if (isRollback) {
          return Collections.emptyList();
        } else {
          for (int i = 0, n = statementList.size(); i < n; i++) {
            Statement stmt = statementList.get(i);
            BatchResult batchResult = batchResultList.get(i);
            try {
                //每一个Statement执行executeBatch
              batchResult.setUpdateCounts(stmt.executeBatch());
              MappedStatement ms = batchResult.getMappedStatement();
              List<Object> parameterObjects = batchResult.getParameterObjects();
              KeyGenerator keyGenerator = ms.getKeyGenerator();
              //执行key
              if (Jdbc3KeyGenerator.class.equals(keyGenerator.getClass())) {
                Jdbc3KeyGenerator jdbc3KeyGenerator = (Jdbc3KeyGenerator) keyGenerator;
                jdbc3KeyGenerator.processBatch(ms, stmt, parameterObjects);
              } else if (!NoKeyGenerator.class.equals(keyGenerator.getClass())) { //issue #141
                for (Object parameter : parameterObjects) {
                  keyGenerator.processAfter(this, ms, stmt, parameter);
                }
              }
            } catch (BatchUpdateException e) {
              StringBuffer message = new StringBuffer();
              message.append(batchResult.getMappedStatement().getId())
                  .append(" (batch index #")
                  .append(i + 1)
                  .append(")")
                  .append(" failed.");
              if (i > 0) {
                message.append(" ")
                    .append(i)
                    .append(" prior sub executor(s) completed successfully, but will be rolled back.");
              }
              throw new BatchExecutorException(message.toString(), e, results, batchResult);
            }
            results.add(batchResult);
          }
          return results;
        }
        } finally {
        for (Statement stmt : statementList) {
          closeStatement(stmt);
        }
        currentSql = null;
        statementList.clear();
        batchResultList.clear();
        }
    }
}

public class CachingExecutor implements Executor {
    //代理Executor
    private Executor delegate;
    //缓存管理器
    private TransactionalCacheManager tcm = new TransactionalCacheManager();

    public void close(boolean forceRollback) {
        try {
            //issues #499, #524 and #573
          if (forceRollback) { 
            tcm.rollback();
          } else {
            tcm.commit();
          }
        } finally {
          delegate.close(forceRollback);
        }
    }

    public boolean isClosed() {
        return delegate.isClosed();
    }

    public int update(MappedStatement ms, Object parameterObject) throws SQLException {
    flushCacheIfRequired(ms);
        return delegate.update(ms, parameterObject);
    }

    public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
        BoundSql boundSql = ms.getBoundSql(parameterObject);
        CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql);
        return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
    }

    public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)
      throws SQLException {
        Cache cache = ms.getCache();
        if (cache != null) {
            flushCacheIfRequired(ms);
            if (ms.isUseCache() && resultHandler == null) {
            ensureNoOutParams(ms, parameterObject, boundSql);
            @SuppressWarnings("unchecked")
            List<E> list = (List<E>) tcm.getObject(cache, key);
            if (list == null) {
                list = delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
                tcm.putObject(cache, key, list); // issue #578. Query must be not synchronized to prevent deadlocks
            }
            return list;
          }
        }
        return delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
    }

    public List<BatchResult> flushStatements() throws SQLException {
        return delegate.flushStatements();
    }

    public void commit(boolean required) throws SQLException {
        delegate.commit(required);
        tcm.commit();
    }

    public void rollback(boolean required) throws SQLException {
        try {
            delegate.rollback(required);
        } finally {
            if (required) {
                tcm.rollback();
            }
        }
    }

    private void ensureNoOutParams(MappedStatement ms, Object parameter, BoundSql boundSql) {
        if (ms.getStatementType() == StatementType.CALLABLE) {
            for (ParameterMapping parameterMapping : boundSql.getParameterMappings()) {
                if (parameterMapping.getMode() != ParameterMode.IN) {
                    throw new ExecutorException("Caching stored procedures with OUT params is not supported.  Please configure useCache=false in " + ms.getId() + " statement.");
                }
            }
        }
    }

    public CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql) {
        return delegate.createCacheKey(ms, parameterObject, rowBounds, boundSql);
    }

    public boolean isCached(MappedStatement ms, CacheKey key) {
        return delegate.isCached(ms, key);
    }

    public void deferLoad(MappedStatement ms, MetaObject resultObject, String property, CacheKey key, Class<?> targetType) {
        delegate.deferLoad(ms, resultObject, property, key, targetType);
    }

    public void clearLocalCache() {
        delegate.clearLocalCache();
    }

    private void flushCacheIfRequired(MappedStatement ms) {
    Cache cache = ms.getCache();
        if (cache != null && ms.isFlushCacheRequired()) {      
            tcm.clear(cache);
        }
    }

    @Override
    public void setExecutorWrapper(Executor executor) {
        throw new UnsupportedOperationException("This method should not be called");
    }
}

3.7、获取BoundSql

MappedStatement的getBoundSql是获取BoundSql对象,这个对象是给接下来的Executor使用,主要通过DynamicSqlSource和RawSqlSource获取

public class DynamicSqlSource implements SqlSource {

    private Configuration configuration;
    private SqlNode rootSqlNode;
    
    public DynamicSqlSource(Configuration configuration, SqlNode rootSqlNode) {
        this.configuration = configuration;
        this.rootSqlNode = rootSqlNode;
    }
    
    public BoundSql getBoundSql(Object parameterObject) {
        //创建DynamicContext 
        DynamicContext context = new DynamicContext(configuration, parameterObject);
        //拼接sql和缓存参数到context中
        rootSqlNode.apply(context);
        //创建SqlSourceBuilder
        SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration);
        Class<?> parameterType = parameterObject == null ? Object.class : parameterObject.getClass();
        //替换sql中的#和构造相应的ParameterMapping,生成StaticSqlSource
        SqlSource sqlSource = sqlSourceParser.parse(context.getSql(), parameterType, context.getBindings());
        //创建BoundSql
        BoundSql boundSql = sqlSource.getBoundSql(parameterObject);
        for (Map.Entry<String, Object> entry : context.getBindings().entrySet()) {
            boundSql.setAdditionalParameter(entry.getKey(), entry.getValue());
        }
        return boundSql;
    }
}

public class RawSqlSource implements SqlSource {

    private final SqlSource sqlSource;

    public RawSqlSource(Configuration configuration, SqlNode rootSqlNode, Class<?> parameterType) {
        this(configuration, getSql(configuration, rootSqlNode), parameterType);
    }

    public RawSqlSource(Configuration configuration, String sql, Class<?> parameterType) {
        //创建SqlSourceBuilder
        SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration);
        Class<?> clazz = parameterType == null ? Object.class : parameterType;
        //替换sql中的#和构造相应的ParameterMapping,生成StaticSqlSource
        sqlSource = sqlSourceParser.parse(sql, clazz, new HashMap<String, Object>());
    }

    private static String getSql(Configuration configuration, SqlNode rootSqlNode) {
        DynamicContext context = new DynamicContext(configuration, null);
        rootSqlNode.apply(context);
        return context.getSql();
    }

    public BoundSql getBoundSql(Object parameterObject) {
        return sqlSource.getBoundSql(parameterObject);
    }
}

public class StaticSqlSource implements SqlSource {
    //执行的预编译sql
    private String sql;
    //参数
    private List<ParameterMapping> parameterMappings;
    private Configuration configuration;
    
    public StaticSqlSource(Configuration configuration, String sql) {
        this(configuration, sql, null);
    }
    
    public StaticSqlSource(Configuration configuration, String sql, List<ParameterMapping> parameterMappings) {
        this.sql = sql;
        this.parameterMappings = parameterMappings;
        this.configuration = configuration;
    }
    
    public BoundSql getBoundSql(Object parameterObject) {
        return new BoundSql(configuration, sql, parameterMappings, parameterObject);
    }
}

public class SqlSourceBuilder extends BaseBuilder {

    private static final String parameterProperties = "javaType,jdbcType,mode,numericScale,resultMap,typeHandler,jdbcTypeName";
    
    public SqlSourceBuilder(Configuration configuration) {
        super(configuration);
    }
    
    public SqlSource parse(String originalSql, Class<?> parameterType, Map<String, Object> additionalParameters) {
        //替换#{}中的内容为?,并构造ParameterMapping
        ParameterMappingTokenHandler handler = new ParameterMappingTokenHandler(configuration, parameterType, additionalParameters);
        GenericTokenParser parser = new GenericTokenParser("#{", "}", handler);
        String sql = parser.parse(originalSql);
        //创建StaticSqlSource
        return new StaticSqlSource(configuration, sql, handler.getParameterMappings());
    }
    
    private static class ParameterMappingTokenHandler extends BaseBuilder implements TokenHandler {
        //存储ParameterMapping
        private List<ParameterMapping> parameterMappings = new ArrayList<ParameterMapping>();
        //参数类型
        private Class<?> parameterType;
        //之前解析绑定的变量
        private MetaObject metaParameters;
    
        public ParameterMappingTokenHandler(Configuration configuration, Class<?> parameterType, Map<String, Object> additionalParameters) {
            super(configuration);
            this.parameterType = parameterType;
            this.metaParameters = configuration.newMetaObject(additionalParameters);
        }
    
        public List<ParameterMapping> getParameterMappings() {
            return parameterMappings;
        }
    
        public String handleToken(String content) {
            //添加ParameterMapping到parameterMappings
            parameterMappings.add(buildParameterMapping(content));
            //将?添加到sql
            return "?";
        }
    
        private ParameterMapping buildParameterMapping(String content) {
            Map<String, String> propertiesMap = parseParameterMapping(content);
            //解析属性名
            String property = propertiesMap.get("property");
            Class<?> propertyType;
            //解析属性类型
            if (metaParameters.hasGetter(property)) { // issue #448 get type from additional params
                propertyType = metaParameters.getGetterType(property);
            } else if (typeHandlerRegistry.hasTypeHandler(parameterType)) {
                propertyType = parameterType;
            } else if (JdbcType.CURSOR.name().equals(propertiesMap.get("jdbcType"))) {
                propertyType = java.sql.ResultSet.class;
            } else if (property != null) {
                MetaClass metaClass = MetaClass.forClass(parameterType);
                if (metaClass.hasGetter(property)) {
                    propertyType = metaClass.getGetterType(property);
                } else {
                    propertyType = Object.class;
                }
            } else {
                propertyType = Object.class;
            }
            ParameterMapping.Builder builder = new ParameterMapping.Builder(configuration, property, propertyType);
            Class<?> javaType = propertyType;
            String typeHandlerAlias = null;
            for (Map.Entry<String, String> entry : propertiesMap.entrySet()) {
                String name = entry.getKey();
                String value = entry.getValue();
                if ("javaType".equals(name)) {
                    javaType = resolveClass(value);
                    builder.javaType(javaType);
                } else if ("jdbcType".equals(name)) {
                      builder.jdbcType(resolveJdbcType(value));
                } else if ("mode".equals(name)) {
                    builder.mode(resolveParameterMode(value));
                } else if ("numericScale".equals(name)) {
                    builder.numericScale(Integer.valueOf(value));
                } else if ("resultMap".equals(name)) {
                    builder.resultMapId(value);
                } else if ("typeHandler".equals(name)) {
                    typeHandlerAlias = value;
                } else if ("jdbcTypeName".equals(name)) {
                    builder.jdbcTypeName(value);
                } else if ("property".equals(name)) {
                  // Do Nothing
                } else if ("expression".equals(name)) {
                    throw new BuilderException("Expression based parameters are not supported yet");
                } else {
                    throw new BuilderException("An invalid property '" + name + "' was found in mapping #{" + content + "}.  Valid properties are " + parameterProperties);
                }
            }
            if (typeHandlerAlias != null) {
                builder.typeHandler(resolveTypeHandler(javaType, typeHandlerAlias));
            }
            return builder.build();
        }
        
        private Map<String, String> parseParameterMapping(String content) {
            try {
                return new ParameterExpression(content);
            } catch (BuilderException ex) {
                throw ex;
            } catch (Exception ex) {
                throw new BuilderException("Parsing error was found in mapping #{" + content + "}.  Check syntax #{property|(expression), var1=value1, var2=value2, ...} ", ex);
            }
        }
    }
}

DynamicContext是获取BoundSql时用来拼接sql,同时存储参数索引和参数值

public class DynamicContext {

    public static final String PARAMETER_OBJECT_KEY = "_parameter";
    public static final String DATABASE_ID_KEY = "_databaseId";

    static {
        OgnlRuntime.setPropertyAccessor(ContextMap.class, new ContextAccessor());
    }
    //变量缓存
    private final ContextMap bindings;
    //sql
    private final StringBuilder sqlBuilder = new StringBuilder();
    //数组循环生成的序列
    private int uniqueNumber = 0;
    public DynamicContext(Configuration configuration, Object parameterObject) {
        //创建ContextMap
        if (parameterObject != null && !(parameterObject instanceof Map)) {
            MetaObject metaObject = configuration.newMetaObject(parameterObject);
            bindings = new ContextMap(metaObject);
        } else {
            bindings = new ContextMap(null);
        }
        bindings.put(PARAMETER_OBJECT_KEY, parameterObject);
        bindings.put(DATABASE_ID_KEY, configuration.getDatabaseId());
    }
    //获取变量缓存
    public Map<String, Object> getBindings() {
        return bindings;
    }
    //缓存变量
    public void bind(String name, Object value) {
        bindings.put(name, value);
    }
    //添加sql
    public void appendSql(String sql) {
        sqlBuilder.append(sql);
        sqlBuilder.append(" ");
    }
    //获取sql
    public String getSql() {
        return sqlBuilder.toString().trim();
    }
    //数组循环生成序列
    public int getUniqueNumber() {
        return uniqueNumber++;
    }
    //DynamicContext存储变量的map
    static class ContextMap extends HashMap<String, Object> {
        private static final long serialVersionUID = 2977601501966151582L;
        //初始化时的变量
        private MetaObject parameterMetaObject;
        public ContextMap(MetaObject parameterMetaObject) {
            this.parameterMetaObject = parameterMetaObject;
        }
    
        @Override
        public Object put(String key, Object value) {
            return super.put(key, value);
        }
        //先从map里获取,然后从parameterMetaObject获取
        @Override
        public Object get(Object key) {
            String strKey = (String) key;
            if (super.containsKey(strKey)) {
                return super.get(strKey);
            }
    
            if (parameterMetaObject != null) {
                Object object = parameterMetaObject.getValue(strKey);
                // issue #61 do not modify the context when reading
                //        if (object != null) { 
                //          super.put(strKey, object);
                //        }
    
                return object;
            }
    
            return null;
        }
      }
}

3.8、StatementHandler执行sql

public abstract class BaseStatementHandler implements StatementHandler {

    protected final Configuration configuration;
    protected final ObjectFactory objectFactory;
    protected final TypeHandlerRegistry typeHandlerRegistry;
    protected final ResultSetHandler resultSetHandler;
    protected final ParameterHandler parameterHandler;

    protected final Executor executor;
    protected final MappedStatement mappedStatement;
    protected final RowBounds rowBounds;
    
    protected BoundSql boundSql;
    protected BaseStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
        this.configuration = mappedStatement.getConfiguration();
        this.executor = executor;
        this.mappedStatement = mappedStatement;
        this.rowBounds = rowBounds;
    
        this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();
        this.objectFactory = configuration.getObjectFactory();
    
        if (boundSql == null) { // issue #435, get the key before calculating the statement
          //执行KeyGenerator
          generateKeys(parameterObject);
          //获取BoundSql
          boundSql = mappedStatement.getBoundSql(parameterObject);
        }
    
        this.boundSql = boundSql;
        //构造ParameterHandler
        this.parameterHandler = configuration.newParameterHandler(mappedStatement, parameterObject, boundSql);
        //构造ResultSetHandler
        this.resultSetHandler = configuration.newResultSetHandler(executor, mappedStatement, rowBounds, parameterHandler, resultHandler, boundSql);
    }
    
    public Statement prepare(Connection connection) throws SQLException {
        ErrorContext.instance().sql(boundSql.getSql());
        Statement statement = null;
        try {
            //实例化Statement
            statement = instantiateStatement(connection);
            setStatementTimeout(statement);
            setFetchSize(statement);
            return statement;
        } catch (SQLException e) {
            closeStatement(statement);
            throw e;
        } catch (Exception e) {
            closeStatement(statement);
            throw new ExecutorException("Error preparing statement.  Cause: " + e, e);
        }
    }
    //设置statement的timeout
    protected void setStatementTimeout(Statement stmt) throws SQLException {
        Integer timeout = mappedStatement.getTimeout();
        Integer defaultTimeout = configuration.getDefaultStatementTimeout();
        if (timeout != null) {
          stmt.setQueryTimeout(timeout);
        } else if (defaultTimeout != null) {
          stmt.setQueryTimeout(defaultTimeout);
        }
  }
  //设置statement的fetchSize
  protected void setFetchSize(Statement stmt) throws SQLException {
    Integer fetchSize = mappedStatement.getFetchSize();
    if (fetchSize != null) {
      stmt.setFetchSize(fetchSize);
    }
  }
  //关闭statement
  protected void closeStatement(Statement statement) {
    try {
      if (statement != null) {
        statement.close();
      }
    } catch (SQLException e) {
      //ignore
    }
  }
  //生成key
  protected void generateKeys(Object parameter) {
    KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();
    ErrorContext.instance().store();
    keyGenerator.processBefore(executor, mappedStatement, null, parameter);
    ErrorContext.instance().recall();
  }
}

public class SimpleStatementHandler extends BaseStatementHandler {
    public int update(Statement statement) throws SQLException {
        String sql = boundSql.getSql();
        Object parameterObject = boundSql.getParameterObject();
        KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();
        int rows;
        if (keyGenerator instanceof Jdbc3KeyGenerator) {
            //执行更新sql和Jdbc3KeyGenerator
            statement.execute(sql, Statement.RETURN_GENERATED_KEYS);
            rows = statement.getUpdateCount();
            keyGenerator.processAfter(executor, mappedStatement, statement, parameterObject);
        } else if (keyGenerator instanceof SelectKeyGenerator) {
            //执行更新sql和SelectKeyGenerator
            statement.execute(sql);
            rows = statement.getUpdateCount();
            keyGenerator.processAfter(executor, mappedStatement, statement, parameterObject);
        } else {
            statement.execute(sql);
            rows = statement.getUpdateCount();
        }
        return rows;
}

    public void batch(Statement statement)
        throws SQLException {
        //批量执行sql
        String sql = boundSql.getSql();
        statement.addBatch(sql);
    }

    public <E> List<E> query(Statement statement, ResultHandler resultHandler)
    throws SQLException {
        //执行查询sql
        String sql = boundSql.getSql();
        statement.execute(sql);
        //调用resultSetHandler处理结果
        return resultSetHandler.<E>handleResultSets(statement);
    }
    
    protected Statement instantiateStatement(Connection connection) throws SQLException {
        //创建Statement
        if (mappedStatement.getResultSetType() != null) {
            return connection.createStatement(mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY);
        } else {
            return connection.createStatement();
        }
    }

    public void parameterize(Statement statement) throws SQLException {
      // N/A
    }
}

public class PreparedStatementHandler extends BaseStatementHandler {

    public int update(Statement statement) throws SQLException {
        //与SimpleStatementHandler区别是使用预编译执行方式
        PreparedStatement ps = (PreparedStatement) statement;
        ps.execute();
        int rows = ps.getUpdateCount();
        Object parameterObject = boundSql.getParameterObject();
        //执行KeyGenerator
        KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();
        keyGenerator.processAfter(executor, mappedStatement, ps, parameterObject);
        return rows;
    }

    public void batch(Statement statement) throws SQLException {
        PreparedStatement ps = (PreparedStatement) statement;
        ps.addBatch();
    }

    public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
        //与SimpleStatementHandler区别是使用预编译执行方式
        PreparedStatement ps = (PreparedStatement) statement;
        //调用resultSetHandler处理结果
        ps.execute();
        return resultSetHandler.<E> handleResultSets(ps);
    }

  protected Statement instantiateStatement(Connection connection) throws SQLException {
    String sql = boundSql.getSql();
    if (mappedStatement.getKeyGenerator() instanceof Jdbc3KeyGenerator) {
      String[] keyColumnNames = mappedStatement.getKeyColumns();
      if (keyColumnNames == null) {
        return connection.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS);
      } else {
        return connection.prepareStatement(sql, keyColumnNames);
      }
    } else if (mappedStatement.getResultSetType() != null) {
      return connection.prepareStatement(sql, mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY);
    } else {
      return connection.prepareStatement(sql);
    }
  }

  public void parameterize(Statement statement) throws SQLException {
    parameterHandler.setParameters((PreparedStatement) statement);
  }

}

public class CallableStatementHandler extends BaseStatementHandler {

    public CallableStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
        super(executor, mappedStatement, parameter, rowBounds, resultHandler, boundSql);
    }

    public int update(Statement statement)
      throws SQLException {
        CallableStatement cs = (CallableStatement) statement;
        cs.execute();
        int rows = cs.getUpdateCount();
        Object parameterObject = boundSql.getParameterObject();
        KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();
        keyGenerator.processAfter(executor, mappedStatement, cs, parameterObject);
        resultSetHandler.handleOutputParameters(cs);
        return rows;
    }

    public void batch(Statement statement)
      throws SQLException {
        CallableStatement cs = (CallableStatement) statement;
        cs.addBatch();
    }

    public <E> List<E> query(Statement statement, ResultHandler resultHandler)
      throws SQLException {
        CallableStatement cs = (CallableStatement) statement;
        cs.execute();
        List<E> resultList = resultSetHandler.<E>handleResultSets(cs);
        resultSetHandler.handleOutputParameters(cs);
        return resultList;
    }

    protected Statement instantiateStatement(Connection connection) throws SQLException {
        String sql = boundSql.getSql();
        if (mappedStatement.getResultSetType() != null) {
          return connection.prepareCall(sql, mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY);
        } else {
          return connection.prepareCall(sql);
        }
    }

    public void parameterize(Statement statement) throws SQLException {
        registerOutputParameters((CallableStatement) statement);
        parameterHandler.setParameters((CallableStatement) statement);
    }

    private void registerOutputParameters(CallableStatement cs) throws SQLException {
        List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
        for (int i = 0, n = parameterMappings.size(); i < n; i++) {
          ParameterMapping parameterMapping = parameterMappings.get(i);
          if (parameterMapping.getMode() == ParameterMode.OUT || parameterMapping.getMode() == ParameterMode.INOUT) {
            if (null == parameterMapping.getJdbcType()) {
              throw new ExecutorException("The JDBC Type must be specified for output parameter.  Parameter: " + parameterMapping.getProperty());
            } else {
              if (parameterMapping.getNumericScale() != null && (parameterMapping.getJdbcType() == JdbcType.NUMERIC || parameterMapping.getJdbcType() == JdbcType.DECIMAL)) {
                cs.registerOutParameter(i + 1, parameterMapping.getJdbcType().TYPE_CODE, parameterMapping.getNumericScale());
              } else {
                if (parameterMapping.getJdbcTypeName() == null) {
                  cs.registerOutParameter(i + 1, parameterMapping.getJdbcType().TYPE_CODE);
                } else {
                  cs.registerOutParameter(i + 1, parameterMapping.getJdbcType().TYPE_CODE, parameterMapping.getJdbcTypeName());
                }
              }
            }
          }
        }
    }

}

3.9、ParameterHandler处理参数

public class DefaultParameterHandler implements ParameterHandler {
  //类型处理器
  private final TypeHandlerRegistry typeHandlerRegistry;
  
  private final MappedStatement mappedStatement;
  private final Object parameterObject;
  private BoundSql boundSql;
  private Configuration configuration;

  public DefaultParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {
    this.mappedStatement = mappedStatement;
    this.configuration = mappedStatement.getConfiguration();
    this.typeHandlerRegistry = mappedStatement.getConfiguration().getTypeHandlerRegistry();
    this.parameterObject = parameterObject;
    this.boundSql = boundSql;
  }

  public Object getParameterObject() {
    return parameterObject;
  }

  public void setParameters(PreparedStatement ps) throws SQLException {
    ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
    //获取BoundSql所有参数
    List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
    if (parameterMappings != null) {
      for (int i = 0; i < parameterMappings.size(); i++) {
        ParameterMapping parameterMapping = parameterMappings.get(i);
        if (parameterMapping.getMode() != ParameterMode.OUT) {
          Object value;
          //获取参数名称
          String propertyName = parameterMapping.getProperty();
          //获取参数值
          if (boundSql.hasAdditionalParameter(propertyName)) { // issue #448 ask first for additional params
            value = boundSql.getAdditionalParameter(propertyName);
          } else if (parameterObject == null) {
            value = null;
          } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
            value = parameterObject;
          } else {
            MetaObject metaObject = configuration.newMetaObject(parameterObject);
            value = metaObject.getValue(propertyName);
          }
          TypeHandler typeHandler = parameterMapping.getTypeHandler();
          JdbcType jdbcType = parameterMapping.getJdbcType();
          if (value == null && jdbcType == null) jdbcType = configuration.getJdbcTypeForNull();
          typeHandler.setParameter(ps, i + 1, value, jdbcType);
        }
      }
    }
  }

}

3.10、ResultSetHandler处理结果

public class DefaultResultSetHandler implements ResultSetHandler {

  private static final Object NO_VALUE = new Object();

  private final Executor executor;
  private final Configuration configuration;
  private final MappedStatement mappedStatement;
  private final RowBounds rowBounds;
  private final ParameterHandler parameterHandler;
  private final ResultHandler resultHandler;
  private final BoundSql boundSql;
  private final TypeHandlerRegistry typeHandlerRegistry;
  private final ObjectFactory objectFactory;

  // nested resultmaps
  private final Map<CacheKey, Object> nestedResultObjects = new HashMap<CacheKey, Object>();
  private final Map<CacheKey, Object> ancestorObjects = new HashMap<CacheKey, Object>();
  private final Map<String, String> ancestorColumnPrefix = new HashMap<String, String>();

  // multiple resultsets
  private final Map<String, ResultMapping> nextResultMaps = new HashMap<String, ResultMapping>();
  private final Map<CacheKey, List<PendingRelation>> pendingRelations = new HashMap<CacheKey, List<PendingRelation>>();
  
  private static class PendingRelation {
    public MetaObject metaObject;
    public ResultMapping propertyMapping;
  }
  
  public DefaultResultSetHandler(Executor executor, MappedStatement mappedStatement, ParameterHandler parameterHandler, ResultHandler resultHandler, BoundSql boundSql,
      RowBounds rowBounds) {
    this.executor = executor;
    this.configuration = mappedStatement.getConfiguration();
    this.mappedStatement = mappedStatement;
    this.rowBounds = rowBounds;
    this.parameterHandler = parameterHandler;
    this.boundSql = boundSql;
    this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();
    this.objectFactory = configuration.getObjectFactory();
    this.resultHandler = resultHandler;
  }

  //
  // HANDLE OUTPUT PARAMETER
  //

  public void handleOutputParameters(CallableStatement cs) throws SQLException {
    final Object parameterObject = parameterHandler.getParameterObject();
    final MetaObject metaParam = configuration.newMetaObject(parameterObject);
    final List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
    for (int i = 0; i < parameterMappings.size(); i++) {
      final ParameterMapping parameterMapping = parameterMappings.get(i);
      if (parameterMapping.getMode() == ParameterMode.OUT || parameterMapping.getMode() == ParameterMode.INOUT) {
        if (ResultSet.class.equals(parameterMapping.getJavaType())) {
          handleRefCursorOutputParameter((ResultSet) cs.getObject(i + 1), parameterMapping, metaParam);
        } else {
          final TypeHandler<?> typeHandler = parameterMapping.getTypeHandler();
          metaParam.setValue(parameterMapping.getProperty(), typeHandler.getResult(cs, i + 1));
        }
      }
    }
  }

  private void handleRefCursorOutputParameter(ResultSet rs, ParameterMapping parameterMapping, MetaObject metaParam) throws SQLException {
    try {
      final String resultMapId = parameterMapping.getResultMapId();
      final ResultMap resultMap = configuration.getResultMap(resultMapId);
      final DefaultResultHandler resultHandler = new DefaultResultHandler(objectFactory);
      final ResultSetWrapper rsw = new ResultSetWrapper(rs, configuration);
      handleRowValues(rsw, resultMap, resultHandler, new RowBounds(), null);
      metaParam.setValue(parameterMapping.getProperty(), resultHandler.getResultList());
    } finally {
      closeResultSet(rs); // issue #228 (close resultsets)
    }
  }

  //
  // HANDLE RESULT SETS
  //

  public List<Object> handleResultSets(Statement stmt) throws SQLException {
    ErrorContext.instance().activity("handling results").object(mappedStatement.getId());
    
    final List<Object> multipleResults = new ArrayList<Object>();

    int resultSetCount = 0;
    ResultSetWrapper rsw = getFirstResultSet(stmt);

    List<ResultMap> resultMaps = mappedStatement.getResultMaps();
    int resultMapCount = resultMaps.size();
    validateResultMapsCount(rsw, resultMapCount);
    while (rsw != null && resultMapCount > resultSetCount) {
      ResultMap resultMap = resultMaps.get(resultSetCount);
      handleResultSet(rsw, resultMap, multipleResults, null);
      rsw = getNextResultSet(stmt);
      cleanUpAfterHandlingResultSet();
      resultSetCount++;
    }

    String[] resultSets = mappedStatement.getResulSets();
    if (resultSets != null) {
      while (rsw != null && resultSetCount < resultSets.length) {
        ResultMapping parentMapping = nextResultMaps.get(resultSets[resultSetCount]);
        if (parentMapping != null) {
          String nestedResultMapId = parentMapping.getNestedResultMapId();
          ResultMap resultMap = configuration.getResultMap(nestedResultMapId);
          handleResultSet(rsw, resultMap, null, parentMapping);
        }
        rsw = getNextResultSet(stmt);
        cleanUpAfterHandlingResultSet();
        resultSetCount++;
      }
    }

    return collapseSingleResultList(multipleResults);
  }

  private ResultSetWrapper getFirstResultSet(Statement stmt) throws SQLException {
    ResultSet rs = stmt.getResultSet();
    while (rs == null) {
      // move forward to get the first resultset in case the driver
      // doesn't return the resultset as the first result (HSQLDB 2.1)
      if (stmt.getMoreResults()) {
        rs = stmt.getResultSet();
      } else {
        if (stmt.getUpdateCount() == -1) {
          // no more results. Must be no resultset
          break;
        }
      }
    }
    return rs != null ? new ResultSetWrapper(rs, configuration) : null;
  }

  private ResultSetWrapper getNextResultSet(Statement stmt) throws SQLException {
    // Making this method tolerant of bad JDBC drivers
    try {
      if (stmt.getConnection().getMetaData().supportsMultipleResultSets()) {
        // Crazy Standard JDBC way of determining if there are more results
        if (!((!stmt.getMoreResults()) && (stmt.getUpdateCount() == -1))) {
          ResultSet rs = stmt.getResultSet();
          return rs != null ? new ResultSetWrapper(rs, configuration) : null;
        }
      }
    } catch (Exception e) {
      // Intentionally ignored.
    }
    return null;
  }

  private void closeResultSet(ResultSet rs) {
    try {
      if (rs != null) {
        rs.close();
      }
    } catch (SQLException e) {
      // ignore
    }
  }

  private void cleanUpAfterHandlingResultSet() {
    nestedResultObjects.clear();
    ancestorColumnPrefix.clear();
  }

  private void validateResultMapsCount(ResultSetWrapper rsw, int resultMapCount) {
    if (rsw != null && resultMapCount < 1) {
      throw new ExecutorException("A query was run and no Result Maps were found for the Mapped Statement '" + mappedStatement.getId()
          + "'.  It's likely that neither a Result Type nor a Result Map was specified.");
    }
  }

  private void handleResultSet(ResultSetWrapper rsw, ResultMap resultMap, List<Object> multipleResults, ResultMapping parentMapping) throws SQLException {
    try {
      if (parentMapping != null) {
        handleRowValues(rsw, resultMap, null, RowBounds.DEFAULT, parentMapping);
      } else {
        if (resultHandler == null) {
          DefaultResultHandler defaultResultHandler = new DefaultResultHandler(objectFactory);
          handleRowValues(rsw, resultMap, defaultResultHandler, rowBounds, null);
          multipleResults.add(defaultResultHandler.getResultList());
        } else {
          handleRowValues(rsw, resultMap, resultHandler, rowBounds, null);
        }
      }
    } finally {
      closeResultSet(rsw.getResultSet()); // issue #228 (close resultsets)
    }
  }

  private List<Object> collapseSingleResultList(List<Object> multipleResults) {
    if (multipleResults.size() == 1) {
      @SuppressWarnings("unchecked")
      List<Object> returned = (List<Object>) multipleResults.get(0);
      return returned;
    }
    return multipleResults;
  }

  //
  // HANDLE ROWS FOR SIMPLE RESULTMAP
  //

  private void handleRowValues(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {
    if (resultMap.hasNestedResultMaps()) {
      ensureNoRowBounds();
      checkResultHandler();
      handleRowValuesForNestedResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
    } else {
      handleRowValuesForSimpleResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
    }
  }  

  private void ensureNoRowBounds() {
    if (configuration.isSafeRowBoundsEnabled() && rowBounds != null && (rowBounds.getLimit() < RowBounds.NO_ROW_LIMIT || rowBounds.getOffset() > RowBounds.NO_ROW_OFFSET)) {
      throw new ExecutorException("Mapped Statements with nested result mappings cannot be safely constrained by RowBounds. "
          + "Use safeRowBoundsEnabled=false setting to bypass this check.");
    }
  }

  protected void checkResultHandler() {
    if (resultHandler != null && configuration.isSafeResultHandlerEnabled() && !mappedStatement.isResultOrdered()) {
      throw new ExecutorException("Mapped Statements with nested result mappings cannot be safely used with a custom ResultHandler. "
          + "Use safeResultHandlerEnabled=false setting to bypass this check " 
          + "or ensure your statement returns ordered data and set resultOrdered=true on it.");
    }
  } 

  private void handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler resultHandler, RowBounds rowBounds, ResultMapping parentMapping)
      throws SQLException {
    DefaultResultContext resultContext = new DefaultResultContext();
    skipRows(rsw.getResultSet(), rowBounds);
    while (shouldProcessMoreRows(resultContext, rowBounds) && rsw.getResultSet().next()) {
      ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(rsw.getResultSet(), resultMap, null);
      Object rowValue = getRowValue(rsw, discriminatedResultMap);
      storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());
    }
  }

  private void storeObject(ResultHandler resultHandler, DefaultResultContext resultContext, Object rowValue, ResultMapping parentMapping, ResultSet rs) throws SQLException {
    if (parentMapping != null) {
      linkToParents(rs, parentMapping, rowValue);
    } else {
      callResultHandler(resultHandler, resultContext, rowValue);
    }
  }

  private void callResultHandler(ResultHandler resultHandler, DefaultResultContext resultContext, Object rowValue) {
    resultContext.nextResultObject(rowValue);
    resultHandler.handleResult(resultContext);
  }

  private boolean shouldProcessMoreRows(ResultContext context, RowBounds rowBounds) throws SQLException {
    return !context.isStopped() && context.getResultCount() < rowBounds.getLimit();
  }

  private void skipRows(ResultSet rs, RowBounds rowBounds) throws SQLException {
    if (rs.getType() != ResultSet.TYPE_FORWARD_ONLY) {
      if (rowBounds.getOffset() != RowBounds.NO_ROW_OFFSET) {
        rs.absolute(rowBounds.getOffset());
      }
    } else {
      for (int i = 0; i < rowBounds.getOffset(); i++) {
        rs.next();
      }
    }
  }

  //
  // GET VALUE FROM ROW FOR SIMPLE RESULT MAP
  //

  private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap) throws SQLException {
    final ResultLoaderMap lazyLoader = new ResultLoaderMap();
    Object resultObject = createResultObject(rsw, resultMap, lazyLoader, null);
    if (resultObject != null && !typeHandlerRegistry.hasTypeHandler(resultMap.getType())) {
      final MetaObject metaObject = configuration.newMetaObject(resultObject);
      boolean foundValues = resultMap.getConstructorResultMappings().size() > 0;
      if (shouldApplyAutomaticMappings(resultMap, !AutoMappingBehavior.NONE.equals(configuration.getAutoMappingBehavior()))) {        
        foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, null) || foundValues;
      }
      foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, null) || foundValues;
      foundValues = lazyLoader.size() > 0 || foundValues;
      resultObject = foundValues ? resultObject : null;
      return resultObject;
    }
    return resultObject;
  }

  private boolean shouldApplyAutomaticMappings(ResultMap resultMap, boolean def) {
    return resultMap.getAutoMapping() != null ? resultMap.getAutoMapping() : def;
  }

  //
  // PROPERTY MAPPINGS
  //

  private boolean applyPropertyMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, ResultLoaderMap lazyLoader, String columnPrefix)
      throws SQLException {
    final List<String> mappedColumnNames = rsw.getMappedColumnNames(resultMap, columnPrefix);
    boolean foundValues = false;
    final List<ResultMapping> propertyMappings = resultMap.getPropertyResultMappings();
    for (ResultMapping propertyMapping : propertyMappings) {
      final String column = prependPrefix(propertyMapping.getColumn(), columnPrefix);
      if (propertyMapping.isCompositeResult() 
          || (column != null && mappedColumnNames.contains(column.toUpperCase(Locale.ENGLISH))) 
          || propertyMapping.getResultSet() != null) {
        Object value = getPropertyMappingValue(rsw.getResultSet(), metaObject, propertyMapping, lazyLoader, columnPrefix);
        final String property = propertyMapping.getProperty(); // issue #541 make property optional
        if (value != NO_VALUE && property != null && (value != null || configuration.isCallSettersOnNulls())) { // issue #377, call setter on nulls
          if (value != null || !metaObject.getSetterType(property).isPrimitive()) {
            metaObject.setValue(property, value);
          }
          foundValues = true;
        }
      }
    }
    return foundValues;
  }

  private Object getPropertyMappingValue(ResultSet rs, MetaObject metaResultObject, ResultMapping propertyMapping, ResultLoaderMap lazyLoader, String columnPrefix)
      throws SQLException {
    if (propertyMapping.getNestedQueryId() != null) {
      return getNestedQueryMappingValue(rs, metaResultObject, propertyMapping, lazyLoader, columnPrefix);
    } else if (propertyMapping.getResultSet() != null) {
      addPendingChildRelation(rs, metaResultObject, propertyMapping);
      return NO_VALUE;
    } else if (propertyMapping.getNestedResultMapId() != null) {
      // the user added a column attribute to a nested result map, ignore it
      return NO_VALUE;
    } else {
      final TypeHandler<?> typeHandler = propertyMapping.getTypeHandler();
      final String column = prependPrefix(propertyMapping.getColumn(), columnPrefix);
      return typeHandler.getResult(rs, column);
    }
  }

  private boolean applyAutomaticMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String columnPrefix) throws SQLException {
    final List<String> unmappedColumnNames = rsw.getUnmappedColumnNames(resultMap, columnPrefix);
    boolean foundValues = false;
    for (String columnName : unmappedColumnNames) {
      String propertyName = columnName;
      if (columnPrefix != null && columnPrefix.length() > 0) {
        // When columnPrefix is specified,
        // ignore columns without the prefix.
        if (columnName.toUpperCase(Locale.ENGLISH).startsWith(columnPrefix)) {
          propertyName = columnName.substring(columnPrefix.length());
        } else {
          continue;
        }
      }
      final String property = metaObject.findProperty(propertyName, configuration.isMapUnderscoreToCamelCase());
      if (property != null && metaObject.hasSetter(property)) {
        final Class<?> propertyType = metaObject.getSetterType(property);
        if (typeHandlerRegistry.hasTypeHandler(propertyType)) {
          final TypeHandler<?> typeHandler = rsw.getTypeHandler(propertyType, columnName);
          final Object value = typeHandler.getResult(rsw.getResultSet(), columnName);
          if (value != null || configuration.isCallSettersOnNulls()) { // issue #377, call setter on nulls
            if (value != null || !propertyType.isPrimitive()) {
              metaObject.setValue(property, value);
            }
            foundValues = true;
          }
        }
      }
    }
    return foundValues;
  }

  // MULTIPLE RESULT SETS

  private void linkToParents(ResultSet rs, ResultMapping parentMapping, Object rowValue) throws SQLException {
    CacheKey parentKey = createKeyForMultipleResults(rs, parentMapping, parentMapping.getColumn(), parentMapping.getForeignColumn());
    List<PendingRelation> parents = pendingRelations.get(parentKey);
    for (PendingRelation parent : parents) {
      if (parent != null) {
        final Object collectionProperty = instantiateCollectionPropertyIfAppropriate(parent.propertyMapping, parent.metaObject);
        if (rowValue != null) {
          if (collectionProperty != null) {
            final MetaObject targetMetaObject = configuration.newMetaObject(collectionProperty);
            targetMetaObject.add(rowValue);
          } else {
            parent.metaObject.setValue(parent.propertyMapping.getProperty(), rowValue);
          }
        }
      }
    }
  }

  private Object instantiateCollectionPropertyIfAppropriate(ResultMapping resultMapping, MetaObject metaObject) {
    final String propertyName = resultMapping.getProperty();
    Object propertyValue = metaObject.getValue(propertyName);
    if (propertyValue == null) {
      Class<?> type = resultMapping.getJavaType();
      if (type == null) {
        type = metaObject.getSetterType(propertyName);
      }
      try {
        if (objectFactory.isCollection(type)) {
          propertyValue = objectFactory.create(type);
          metaObject.setValue(propertyName, propertyValue);
          return propertyValue;
        }
      } catch (Exception e) {
        throw new ExecutorException("Error instantiating collection property for result '" + resultMapping.getProperty() + "'.  Cause: " + e, e);
      }
    } else if (objectFactory.isCollection(propertyValue.getClass())) {
      return propertyValue;
    }
    return null;
  }

  private void addPendingChildRelation(ResultSet rs, MetaObject metaResultObject, ResultMapping parentMapping) throws SQLException {
    CacheKey cacheKey = createKeyForMultipleResults(rs, parentMapping, parentMapping.getColumn(), parentMapping.getColumn());
    PendingRelation deferLoad = new PendingRelation();
    deferLoad.metaObject = metaResultObject;
    deferLoad.propertyMapping = parentMapping;
    List<PendingRelation> relations = pendingRelations.get(cacheKey);
    // issue #255
    if (relations == null) {
      relations = new ArrayList<DefaultResultSetHandler.PendingRelation>();
      pendingRelations.put(cacheKey, relations);
    }
    relations.add(deferLoad);
    ResultMapping previous = nextResultMaps.get(parentMapping.getResultSet());
    if (previous == null) {
      nextResultMaps.put(parentMapping.getResultSet(), parentMapping);
    } else {
      if (!previous.equals(parentMapping)) {
        throw new ExecutorException("Two different properties are mapped to the same resultSet");
      }
    }
  }

  private CacheKey createKeyForMultipleResults(ResultSet rs, ResultMapping resultMapping, String names, String columns) throws SQLException {
    CacheKey cacheKey = new CacheKey();
    cacheKey.update(resultMapping);
    if (columns != null && names != null) {
      String[] columnsArray = columns.split(",");
      String[] namesArray = names.split(",");
      for (int i = 0 ; i < columnsArray.length ; i++) {
        Object value = rs.getString(columnsArray[i]);
        if (value != null) {
          cacheKey.update(namesArray[i]);
          cacheKey.update(value);
        }
      }
    }
    return cacheKey;
  }

  //
  // INSTANTIATION & CONSTRUCTOR MAPPING
  //

  private Object createResultObject(ResultSetWrapper rsw, ResultMap resultMap, ResultLoaderMap lazyLoader, String columnPrefix) throws SQLException {
    final List<Class<?>> constructorArgTypes = new ArrayList<Class<?>>();
    final List<Object> constructorArgs = new ArrayList<Object>();
    final Object resultObject = createResultObject(rsw, resultMap, constructorArgTypes, constructorArgs, columnPrefix);
    if (resultObject != null && !typeHandlerRegistry.hasTypeHandler(resultMap.getType())) {
      final List<ResultMapping> propertyMappings = resultMap.getPropertyResultMappings();
      for (ResultMapping propertyMapping : propertyMappings) {
        if (propertyMapping.getNestedQueryId() != null && propertyMapping.isLazy()) { // issue gcode #109 && issue #149
          return configuration.getProxyFactory().createProxy(resultObject, lazyLoader, configuration, objectFactory, constructorArgTypes, constructorArgs);
        }
      }
    }
    return resultObject;
  }

  private Object createResultObject(ResultSetWrapper rsw, ResultMap resultMap, List<Class<?>> constructorArgTypes, List<Object> constructorArgs, String columnPrefix)
      throws SQLException {
    final Class<?> resultType = resultMap.getType();
    final List<ResultMapping> constructorMappings = resultMap.getConstructorResultMappings();
    if (typeHandlerRegistry.hasTypeHandler(resultType)) {
      return createPrimitiveResultObject(rsw, resultMap, columnPrefix);
    } else if (constructorMappings.size() > 0) {
      return createParameterizedResultObject(rsw, resultType, constructorMappings, constructorArgTypes, constructorArgs, columnPrefix);
    } else {
      return objectFactory.create(resultType);
    }
  }

  private Object createParameterizedResultObject(ResultSetWrapper rsw, Class<?> resultType, List<ResultMapping> constructorMappings, List<Class<?>> constructorArgTypes,
      List<Object> constructorArgs, String columnPrefix) throws SQLException {
    boolean foundValues = false;
    for (ResultMapping constructorMapping : constructorMappings) {
      final Class<?> parameterType = constructorMapping.getJavaType();
      final String column = constructorMapping.getColumn();
      final Object value;
      if (constructorMapping.getNestedQueryId() != null) {
        value = getNestedQueryConstructorValue(rsw.getResultSet(), constructorMapping, columnPrefix);
      } else if (constructorMapping.getNestedResultMapId() != null) {
        final ResultMap resultMap = configuration.getResultMap(constructorMapping.getNestedResultMapId());
        value = getRowValue(rsw, resultMap);
      } else {
        final TypeHandler<?> typeHandler = constructorMapping.getTypeHandler();
        value = typeHandler.getResult(rsw.getResultSet(), prependPrefix(column, columnPrefix));
      }
      constructorArgTypes.add(parameterType);
      constructorArgs.add(value);
      foundValues = value != null || foundValues;
    }
    return foundValues ? objectFactory.create(resultType, constructorArgTypes, constructorArgs) : null;
  }

  private Object createPrimitiveResultObject(ResultSetWrapper rsw, ResultMap resultMap, String columnPrefix) throws SQLException {
    final Class<?> resultType = resultMap.getType();
    final String columnName;
    if (resultMap.getResultMappings().size() > 0) {
      final List<ResultMapping> resultMappingList = resultMap.getResultMappings();
      final ResultMapping mapping = resultMappingList.get(0);
      columnName = prependPrefix(mapping.getColumn(), columnPrefix);
    } else {
      columnName = rsw.getColumnNames().get(0);
    }
    final TypeHandler<?> typeHandler = rsw.getTypeHandler(resultType, columnName);
    return typeHandler.getResult(rsw.getResultSet(), columnName);
  }

  //
  // NESTED QUERY
  //

  private Object getNestedQueryConstructorValue(ResultSet rs, ResultMapping constructorMapping, String columnPrefix) throws SQLException {
    final String nestedQueryId = constructorMapping.getNestedQueryId();
    final MappedStatement nestedQuery = configuration.getMappedStatement(nestedQueryId);
    final Class<?> nestedQueryParameterType = nestedQuery.getParameterMap().getType();
    final Object nestedQueryParameterObject = prepareParameterForNestedQuery(rs, constructorMapping, nestedQueryParameterType, columnPrefix);
    Object value = null;
    if (nestedQueryParameterObject != null) {
      final BoundSql nestedBoundSql = nestedQuery.getBoundSql(nestedQueryParameterObject);
      final CacheKey key = executor.createCacheKey(nestedQuery, nestedQueryParameterObject, RowBounds.DEFAULT, nestedBoundSql);
      final Class<?> targetType = constructorMapping.getJavaType();
      final ResultLoader resultLoader = new ResultLoader(configuration, executor, nestedQuery, nestedQueryParameterObject, targetType, key, nestedBoundSql);
      value = resultLoader.loadResult();
    }
    return value;
  }

  private Object getNestedQueryMappingValue(ResultSet rs, MetaObject metaResultObject, ResultMapping propertyMapping, ResultLoaderMap lazyLoader, String columnPrefix)
      throws SQLException {
    final String nestedQueryId = propertyMapping.getNestedQueryId();
    final String property = propertyMapping.getProperty();
    final MappedStatement nestedQuery = configuration.getMappedStatement(nestedQueryId);
    final Class<?> nestedQueryParameterType = nestedQuery.getParameterMap().getType();
    final Object nestedQueryParameterObject = prepareParameterForNestedQuery(rs, propertyMapping, nestedQueryParameterType, columnPrefix);
    Object value = NO_VALUE;
    if (nestedQueryParameterObject != null) {
      final BoundSql nestedBoundSql = nestedQuery.getBoundSql(nestedQueryParameterObject);
      final CacheKey key = executor.createCacheKey(nestedQuery, nestedQueryParameterObject, RowBounds.DEFAULT, nestedBoundSql);
      final Class<?> targetType = propertyMapping.getJavaType();
      if (executor.isCached(nestedQuery, key)) {
        executor.deferLoad(nestedQuery, metaResultObject, property, key, targetType);
      } else {
        final ResultLoader resultLoader = new ResultLoader(configuration, executor, nestedQuery, nestedQueryParameterObject, targetType, key, nestedBoundSql);
        if (propertyMapping.isLazy()) {
          lazyLoader.addLoader(property, metaResultObject, resultLoader);
        } else {
          value = resultLoader.loadResult();
        }
      }
    }
    return value;
  }

  private Object prepareParameterForNestedQuery(ResultSet rs, ResultMapping resultMapping, Class<?> parameterType, String columnPrefix) throws SQLException {
    if (resultMapping.isCompositeResult()) {
      return prepareCompositeKeyParameter(rs, resultMapping, parameterType, columnPrefix);
    } else {
      return prepareSimpleKeyParameter(rs, resultMapping, parameterType, columnPrefix);
    }
  }

  private Object prepareSimpleKeyParameter(ResultSet rs, ResultMapping resultMapping, Class<?> parameterType, String columnPrefix) throws SQLException {
    final TypeHandler<?> typeHandler;
    if (typeHandlerRegistry.hasTypeHandler(parameterType)) {
      typeHandler = typeHandlerRegistry.getTypeHandler(parameterType);
    } else {
      typeHandler = typeHandlerRegistry.getUnknownTypeHandler();
    }
    return typeHandler.getResult(rs, prependPrefix(resultMapping.getColumn(), columnPrefix));
  }

  private Object prepareCompositeKeyParameter(ResultSet rs, ResultMapping resultMapping, Class<?> parameterType, String columnPrefix) throws SQLException {
    final Object parameterObject = instantiateParameterObject(parameterType);
    final MetaObject metaObject = configuration.newMetaObject(parameterObject);
    boolean foundValues = false;
    for (ResultMapping innerResultMapping : resultMapping.getComposites()) {
      final Class<?> propType = metaObject.getSetterType(innerResultMapping.getProperty());
      final TypeHandler<?> typeHandler = typeHandlerRegistry.getTypeHandler(propType);
      final Object propValue = typeHandler.getResult(rs, prependPrefix(innerResultMapping.getColumn(), columnPrefix));
      if (propValue != null) { // issue #353 & #560 do not execute nested query if key is null
        metaObject.setValue(innerResultMapping.getProperty(), propValue);
        foundValues = true;
      }
    }
    return foundValues ? parameterObject : null;
  }

  private Object instantiateParameterObject(Class<?> parameterType) {
    if (parameterType == null) {
      return new HashMap<Object, Object>();
    } else {
      return objectFactory.create(parameterType);
    }
  }

  //
  // DISCRIMINATOR
  //

  public ResultMap resolveDiscriminatedResultMap(ResultSet rs, ResultMap resultMap, String columnPrefix) throws SQLException {
    Set<String> pastDiscriminators = new HashSet<String>();
    Discriminator discriminator = resultMap.getDiscriminator();
    while (discriminator != null) {
      final Object value = getDiscriminatorValue(rs, discriminator, columnPrefix);
      final String discriminatedMapId = discriminator.getMapIdFor(String.valueOf(value));
      if (configuration.hasResultMap(discriminatedMapId)) {
        resultMap = configuration.getResultMap(discriminatedMapId);
        Discriminator lastDiscriminator = discriminator;
        discriminator = resultMap.getDiscriminator();
        if (discriminator == lastDiscriminator || !pastDiscriminators.add(discriminatedMapId)) {
          break;
        }
      } else {
        break;
      }
    }
    return resultMap;
  }

  private Object getDiscriminatorValue(ResultSet rs, Discriminator discriminator, String columnPrefix) throws SQLException {
    final ResultMapping resultMapping = discriminator.getResultMapping();
    final TypeHandler<?> typeHandler = resultMapping.getTypeHandler();
    return typeHandler.getResult(rs, prependPrefix(resultMapping.getColumn(), columnPrefix));
  }

  private String prependPrefix(String columnName, String prefix) {
    if (columnName == null || columnName.length() == 0 || prefix == null || prefix.length() == 0) {
      return columnName;
    }
    return prefix + columnName;
  }

  //
  // HANDLE NESTED RESULT MAPS
  //

  private void handleRowValuesForNestedResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {
    final DefaultResultContext resultContext = new DefaultResultContext();
    skipRows(rsw.getResultSet(), rowBounds);
    Object rowValue = null;
    while (shouldProcessMoreRows(resultContext, rowBounds) && rsw.getResultSet().next()) {
      final ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(rsw.getResultSet(), resultMap, null);
      final CacheKey rowKey = createRowKey(discriminatedResultMap, rsw, null);
      Object partialObject = nestedResultObjects.get(rowKey);
      if (mappedStatement.isResultOrdered()) { // issue #577 && #542
        if (partialObject == null && rowValue != null) {
          nestedResultObjects.clear();
          storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());
        }
        rowValue = getRowValue(rsw, discriminatedResultMap, rowKey, rowKey, null, partialObject);
      } else {
        rowValue = getRowValue(rsw, discriminatedResultMap, rowKey, rowKey, null, partialObject);
        if (partialObject == null) {
          storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());
        }
      }
    }
    if (rowValue != null && mappedStatement.isResultOrdered() && shouldProcessMoreRows(resultContext, rowBounds)) {
      storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());
    }
  }
  
  //
  // GET VALUE FROM ROW FOR NESTED RESULT MAP
  //

  private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap, CacheKey combinedKey, CacheKey absoluteKey, String columnPrefix, Object partialObject) throws SQLException {
    final String resultMapId = resultMap.getId();
    Object resultObject = partialObject;
    if (resultObject != null) {
      final MetaObject metaObject = configuration.newMetaObject(resultObject);
      putAncestor(absoluteKey, resultObject, resultMapId, columnPrefix);
      applyNestedResultMappings(rsw, resultMap, metaObject, columnPrefix, combinedKey, false);
      ancestorObjects.remove(absoluteKey);
    } else {
      final ResultLoaderMap lazyLoader = new ResultLoaderMap();
      resultObject = createResultObject(rsw, resultMap, lazyLoader, columnPrefix);
      if (resultObject != null && !typeHandlerRegistry.hasTypeHandler(resultMap.getType())) {
        final MetaObject metaObject = configuration.newMetaObject(resultObject);
        boolean foundValues = resultMap.getConstructorResultMappings().size() > 0;
        if (shouldApplyAutomaticMappings(resultMap, AutoMappingBehavior.FULL.equals(configuration.getAutoMappingBehavior()))) {
          foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, columnPrefix) || foundValues;
        }        
        foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, columnPrefix) || foundValues;
        putAncestor(absoluteKey, resultObject, resultMapId, columnPrefix);
        foundValues = applyNestedResultMappings(rsw, resultMap, metaObject, columnPrefix, combinedKey, true) || foundValues;
        ancestorObjects.remove(absoluteKey);
        foundValues = lazyLoader.size() > 0 || foundValues;
        resultObject = foundValues ? resultObject : null;
      }
      if (combinedKey != CacheKey.NULL_CACHE_KEY) nestedResultObjects.put(combinedKey, resultObject);
    }
    return resultObject;
  }

  private void putAncestor(CacheKey rowKey, Object resultObject, String resultMapId, String columnPrefix) {
    if (!ancestorColumnPrefix.containsKey(resultMapId)) {
      ancestorColumnPrefix.put(resultMapId, columnPrefix);
    }
    ancestorObjects.put(rowKey, resultObject);
  }

  //
  // NESTED RESULT MAP (JOIN MAPPING)
  //

  private boolean applyNestedResultMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String parentPrefix, CacheKey parentRowKey, boolean newObject) {
    boolean foundValues = false;
    for (ResultMapping resultMapping : resultMap.getPropertyResultMappings()) {
      final String nestedResultMapId = resultMapping.getNestedResultMapId();
      if (nestedResultMapId != null && resultMapping.getResultSet() == null) {
        try {
          final String columnPrefix = getColumnPrefix(parentPrefix, resultMapping);
          final ResultMap nestedResultMap = getNestedResultMap(rsw.getResultSet(), nestedResultMapId, columnPrefix);
          CacheKey rowKey = null;
          Object ancestorObject = null;
          if (ancestorColumnPrefix.containsKey(nestedResultMapId)) {
            rowKey = createRowKey(nestedResultMap, rsw, ancestorColumnPrefix.get(nestedResultMapId));
            ancestorObject = ancestorObjects.get(rowKey);
          }
          if (ancestorObject != null) { 
            if (newObject) metaObject.setValue(resultMapping.getProperty(), ancestorObject);
          } else {
            rowKey = createRowKey(nestedResultMap, rsw, columnPrefix);
            final CacheKey combinedKey = combineKeys(rowKey, parentRowKey);            
            Object rowValue = nestedResultObjects.get(combinedKey);
            boolean knownValue = (rowValue != null);
            final Object collectionProperty = instantiateCollectionPropertyIfAppropriate(resultMapping, metaObject);            
            if (anyNotNullColumnHasValue(resultMapping, columnPrefix, rsw.getResultSet())) {
              rowValue = getRowValue(rsw, nestedResultMap, combinedKey, rowKey, columnPrefix, rowValue);
              if (rowValue != null && !knownValue) {
                if (collectionProperty != null) {
                  final MetaObject targetMetaObject = configuration.newMetaObject(collectionProperty);
                  targetMetaObject.add(rowValue);
                } else {
                  metaObject.setValue(resultMapping.getProperty(), rowValue);
                }
                foundValues = true;
              }
            }
          }
        } catch (SQLException e) {
          throw new ExecutorException("Error getting nested result map values for '" + resultMapping.getProperty() + "'.  Cause: " + e, e);
        }
      }
    }
    return foundValues;
  }

  private String getColumnPrefix(String parentPrefix, ResultMapping resultMapping) {
    final StringBuilder columnPrefixBuilder = new StringBuilder();
    if (parentPrefix != null) columnPrefixBuilder.append(parentPrefix);
    if (resultMapping.getColumnPrefix() != null) columnPrefixBuilder.append(resultMapping.getColumnPrefix());
    final String columnPrefix = columnPrefixBuilder.length() == 0 ? null : columnPrefixBuilder.toString().toUpperCase(Locale.ENGLISH);
    return columnPrefix;
  }

  private boolean anyNotNullColumnHasValue(ResultMapping resultMapping, String columnPrefix, ResultSet rs) throws SQLException {
    Set<String> notNullColumns = resultMapping.getNotNullColumns();
    boolean anyNotNullColumnHasValue = true;
    if (notNullColumns != null && !notNullColumns.isEmpty()) {
      anyNotNullColumnHasValue = false;
      for (String column: notNullColumns) {
        rs.getObject(prependPrefix(column, columnPrefix));
        if (!rs.wasNull()) {
          anyNotNullColumnHasValue = true;
          break;
        }
      }
    }
    return anyNotNullColumnHasValue;
  }

  private ResultMap getNestedResultMap(ResultSet rs, String nestedResultMapId, String columnPrefix) throws SQLException {
    ResultMap nestedResultMap = configuration.getResultMap(nestedResultMapId);
    nestedResultMap = resolveDiscriminatedResultMap(rs, nestedResultMap, columnPrefix);
    return nestedResultMap;
  }

  //
  // UNIQUE RESULT KEY
  //

  private CacheKey createRowKey(ResultMap resultMap, ResultSetWrapper rsw, String columnPrefix) throws SQLException {
    final CacheKey cacheKey = new CacheKey();
    cacheKey.update(resultMap.getId());
    List<ResultMapping> resultMappings = getResultMappingsForRowKey(resultMap);
    if (resultMappings.size() == 0) {
      if (Map.class.isAssignableFrom(resultMap.getType())) {
        createRowKeyForMap(rsw, cacheKey);
      } else {
        createRowKeyForUnmappedProperties(resultMap, rsw, cacheKey, columnPrefix);
      }
    } else {
      createRowKeyForMappedProperties(resultMap, rsw, cacheKey, resultMappings, columnPrefix);
    }
    return cacheKey;
  }

  private CacheKey combineKeys(CacheKey rowKey, CacheKey parentRowKey) {
    if (rowKey.getUpdateCount() > 1 && parentRowKey.getUpdateCount() > 1) {
      CacheKey combinedKey;
      try {
        combinedKey = rowKey.clone();
      } catch (CloneNotSupportedException e) {
        throw new ExecutorException("Error cloning cache key.  Cause: " + e, e);
      }
      combinedKey.update(parentRowKey);
      return combinedKey;
    }
    return CacheKey.NULL_CACHE_KEY;
  }

  private List<ResultMapping> getResultMappingsForRowKey(ResultMap resultMap) {
    List<ResultMapping> resultMappings = resultMap.getIdResultMappings();
    if (resultMappings.size() == 0) {
      resultMappings = resultMap.getPropertyResultMappings();
    }
    return resultMappings;
  }

  private void createRowKeyForMappedProperties(ResultMap resultMap, ResultSetWrapper rsw, CacheKey cacheKey, List<ResultMapping> resultMappings, String columnPrefix) throws SQLException {
    for (ResultMapping resultMapping : resultMappings) {
      if (resultMapping.getNestedResultMapId() != null && resultMapping.getResultSet() == null) { // Issue #392
        final ResultMap nestedResultMap = configuration.getResultMap(resultMapping.getNestedResultMapId());
        createRowKeyForMappedProperties(nestedResultMap, rsw, cacheKey, nestedResultMap.getConstructorResultMappings(),
            prependPrefix(resultMapping.getColumnPrefix(), columnPrefix));
      } else if (resultMapping.getNestedQueryId() == null) {
        final String column = prependPrefix(resultMapping.getColumn(), columnPrefix);
        final TypeHandler<?> th = resultMapping.getTypeHandler();
        List<String> mappedColumnNames = rsw.getMappedColumnNames(resultMap, columnPrefix);
        if (column != null && mappedColumnNames.contains(column.toUpperCase(Locale.ENGLISH))) { // Issue #114
          final Object value = th.getResult(rsw.getResultSet(), column);
          if (value != null) {
            cacheKey.update(column);
            cacheKey.update(value);
          }
        }
      }
    }
  }

  private void createRowKeyForUnmappedProperties(ResultMap resultMap, ResultSetWrapper rsw, CacheKey cacheKey, String columnPrefix) throws SQLException {
    final MetaClass metaType = MetaClass.forClass(resultMap.getType());
    List<String> unmappedColumnNames = rsw.getUnmappedColumnNames(resultMap, columnPrefix);
    for (String column : unmappedColumnNames) {
      String property = column;
      if (columnPrefix != null && columnPrefix.length() > 0) {
        // When columnPrefix is specified,
        // ignore columns without the prefix.
        if (column.toUpperCase(Locale.ENGLISH).startsWith(columnPrefix)) {
          property = column.substring(columnPrefix.length());
        } else {
          continue;
        }
      }
      if (metaType.findProperty(property, configuration.isMapUnderscoreToCamelCase()) != null) {
        String value = rsw.getResultSet().getString(column);
        if (value != null) {
          cacheKey.update(column);
          cacheKey.update(value);
        }
      }
    }
  }

  private void createRowKeyForMap(ResultSetWrapper rsw, CacheKey cacheKey) throws SQLException {
    List<String> columnNames = rsw.getColumnNames();
    for (String columnName : columnNames) {
      final String value = rsw.getResultSet().getString(columnName);
      if (value != null) {
        cacheKey.update(columnName);
        cacheKey.update(value);
      }
    }
  }

}