1.解析xml的主流程
解析xml,转换成sqlSession,一切从 SqlSessionFactoryBean 开始:
SqlSessionFactory的初始化: org.mybatis.spring.SqlSessionFactoryBean#afterPropertiesSet
其中,解析mapper的xml的代码为:
xml解析的关键链路:
org.apache.ibatis.builder.xml.XMLMapperBuilder#parse
org.apache.ibatis.builder.xml.XMLMapperBuilder#configurationElement
org.apache.ibatis.builder.xml.XMLStatementBuilder#parseStatementNode
org.apache.ibatis.builder.MapperBuilderAssistant#addMappedStatement
最终,从xml中解析的sql缓存在:
org.apache.ibatis.session.Configuration#mappedStatements
以上为解析的主流程,其中具体的将xml解析成sql的逻辑为XMLStatementBuilder#parseStatementNode
,在下一节详细分析
2.将xml解析成sql
将xml转成sql的关键步骤 是在上述 XMLStatementBuilder#parseStatementNode
中调用LanguageDriver#createSqlSource
对于xml而言,具体的方法路径为:
-
org.apache.ibatis.scripting.xmltags.XMLLanguageDriver#createSqlSource
-
org.apache.ibatis.scripting.xmltags.XMLScriptBuilder#parseScriptNode
-
org.apache.ibatis.scripting.defaults.RawSqlSource#RawSqlSource
(创建实例方法)
将xml中的sql片段(如 forech if 等标签)解析成完成的sql的方法:
org.apache.ibatis.scripting.defaults.RawSqlSource#getSql
不同的标签的解析动作委托给不同的SqlNode实现:
将转换成的sql进一步解析:
org.apache.ibatis.builder.SqlSourceBuilder#parse
其转换效果示例为:
转换前:
SELECT
COUNT (1)
FROM
POS_AUTH_INFO INFO
WHERE
MANAGER_ID = # { managerId }
AND AUTH_MANAGER_ID = # { authManagerId }
AND STATUS = # { status }
AND AUTH_PRDT_FLAG = # { authPrdtFlag }
转换后:
SELECT
COUNT (1)
FROM
POS_AUTH_INFO INFO
WHERE
MANAGER_ID = ?
AND AUTH_MANAGER_ID = ?
AND STATUS = ?
AND AUTH_PRDT_FLAG = ?
3.mapper的执行流程
mapper的执行入口:
org.apache.ibatis.binding.MapperMethod#execute
以查询方法为例,查询方法的关键位置:
org.apache.ibatis.session.defaults.DefaultSqlSession#selectList
具体的调用链路为(根据实际项目的不同,可能有差异):
org.apache.ibatis.executor.CachingExecutor#query
org.apache.ibatis.executor.CachingExecutor#query
org.apache.ibatis.executor.BaseExecutor#query
org.apache.ibatis.executor.BaseExecutor#queryFromDatabase
org.apache.ibatis.executor.SimpleExecutor#doQuery
org.apache.ibatis.executor.statement.RoutingStatementHandler#query
org.apache.ibatis.executor.statement.PreparedStatementHandler#query
终极方法调用是:
com.alibaba.druid.pool.DruidPooledPreparedStatement#execute
显然,项目是用到了Druid框架
上述链路中,excutor实现为CachingExecutor
, 实际上,根据不同的配置会采用不同的实现,具体参考:
org.apache.ibatis.session.Configuration#newExecutor
sql中参数的绑定(例如在CachingExecutor#query有调用 ):
org.apache.ibatis.mapping.MappedStatement#getBoundSql
sql中的参数绑定:
org.apache.ibatis.executor.SimpleExecutor#doQuery
org.apache.ibatis.executor.SimpleExecutor#prepareStatement
org.apache.ibatis.scripting.defaults.DefaultParameterHandler#setParameters