MyBatis执行流程如下所示。
sqlSession
上层获取mapper时调用sqlSession.getMapper,defaultSqlSession实现比较简单,调用configuration.getMapper获取mapper。
configuration
和sqlSession类似,configuration会调用mapperRegistry.getMapper获取mapper。
mapperRegistry
在mapperRegistry实例化一个mapper的代理对象,实际代理逻辑在mapperProxy里执行。
mapperProxy
获取mapperProxy后会调用定义的方法执行,这时会调用mapperProxy.invoke执行代理逻辑,在invoke方法里面,封装一个mapperMethod对象,mapperMethod对象执行真正的代理逻辑。
mapperMethod
在mapperMethod维护了两个变量,一个是command,保存了mappedStatement信息、待执行SQL类型,一个是method,保存了方法的返回值信息、参数信息,method变量会解析方法入参,用key-value形式保存,key是变量出现的顺序,value是变量别名或自动生成的编号。
代理逻辑执行会调用mapperMethod.execute,这里会判断执行SQL的类型,按类型的不同调用到sqlSession不同的方法。
executor
在mapperMethod调用sqlSession执行SQL语句时,sqlSession获取mappedStatement后把执行逻辑委托executor执行。
executor的继承关系如下所示,正常情况下使用的是cachingExecutor,这里使用装饰器模式,cachingExecutor会把调用委托给baseExecutor实现类执行,在baseExecutor实现类外面包一层缓存。
在executor执行时会调用mappedStatement获取boundSql,可以认为是待执行SQL语句一个封装,获取boundSql会把配置阶段解析生成的sqlNode拼成代执行的SQL,会把${}用配置的值替换,把#{}替换为?。
在executor执行时会创建statementHandler,使用statementHandler执行SQL语句。
statementHandler
上面说executor执行时会创建statementHandler,使用statementHandler执行SQL语句,正常情况下直接接触的statementHandler是routingStatementHandler,
statementHandler的继承关系如下所示。
在statementHandler执行的时候,会执行初始化、执行、处理结果这几个步骤,初始化使用parameterHandler把入参设置到statement,执行使用JDBC提供的statement.execute执行SQL语句,查询操作会调用resultSetHandler.handlerResultSets处理查询的结果封装成对象。
parameterHandler
使用typeHandler调用JDBC提供statement方法设置参数。
resultSetHandler
使用resultHandler转换执行SQL语句结果。