参数解析
ParamNameResolver
类用于解析接口方法中传递的参数
重要方法:getNamedParams
解析步骤:
- 如果没有参数,直接返回null
- 如果没有并且参数数量为1,则取第一个参数值
- 在有注解或者参数数量大于1的情况下,将参数转为Map形式,有注解的,map中的key为注解的value值,没有注解的使用参数顺序号,从0开始。且mybatis会自动生成参数名前缀为
param
的参数。
//key -> value
0 -> 123
1 -> 234
param0 -> 123
param1 -> 234
其中key=0和param0表示的同一个参数,两种key
ParameterMapping
为每个参数名称,参数类型的处理类。
ParameterMappingTokenHandler
用于处理解析Sql中的占位符变量
方法体
org.apache.ibatis.mapping.MappedStatement
类用于解析并xml文件中的每个方法标签中的Sql并将其转换为java中的代码格式。
主要结构包括
参数名 | 类型 | 功能 | 备注 |
---|---|---|---|
configuration | Configuration | 整个mybatis所有配置信息类 | |
id | 唯一指定该方法的id,为方法名或全限定方法名 | ||
statementType | StatementType | Sql语句的类型,STATEMENT 、PREPARED 、CALLABLE |
|
resultSetType | ResultSetType | 结果集类型。FORWARD_ONLY 、TYPE_SCROLL_INSENSITIVE 、TYPE_SCROLL_SENSITIVE |
|
sqlSource | SqlSource | 内部结构为BoundSql |
BoundSql包含完整的Sql,含有类型信息的参数以及参数名和参数值的映射表 |
parameterMap | ParameterMap | 待补充描述 | |
resultMaps | List |
待补充描述 | |
sqlCommandType | SqlCommandType | Sql命令的类型。包括:INSERT , UPDATE ,DELETE ,SELECT ,FLUSH |
|
keyGenerator | KeyGenerator | 主键生成的类。实现类有:SelectKeyGenerator 、Jdbc3KeyGenerator 、NoKeyGenerator |
|
keyProperties | String[] | 指定key的属性,该属性为pojo的属性名 | |
keyColumns | String[] | 指定key的列,该属为表中的字段 | |
statementLog | Log | 指定的语句打印的日志类 | |
lang | LanguageDriver | 生成Sql的驱动器,实现类有:XMLLanguageDriver 和RawLanguageDriver 。其中RawLanguageDriver 是继承的XMLLanguageDriver ,且不支持胴体Sql |
在MappedStatement.getBoundSql
通过传入的参数,完成Sql的解析和构建。
Sql解析
DynamicContext
为主要的动态Sql的操作类
其中有参数bindings,结构为ContextMap,重写了hashMap的get方法。在实例化DynamicContext
时会设置_parameter
和_databaseId
两个key
SqlSourceBuilder
会通过parse
方法将原始Sql和绑定的参数进行解析,使用GenericTokenParser
将初步解析出来的动态sql中的#{var}
替换为?
,并将对应的var
通过ParameterMappingTokenHandler
设置到ParameterMapping
中。
Sql到这里已经解析完毕,可以将其转化为你静态Sql了,将解析后的sql赋给StaticSqlSource
生成新对象
动态Sql的片段
在Mybatis中,初始化时会根据标签,将Sql代码片段解析到对应的SqlNode中,在实际执行时进行解析。
SqlNode集合
类型 | 功能 | 备注 |
---|---|---|
MixedSqlNode | 整个Sql语句的总的SqlNode | 不具有实际的解析能力。是集合该sql下所有sql片段的地方。 |
StaticTextSqlNode | 存储Sql中静态的文本Sql | 只存储不解析 |
ForEachSqlNode | 对应xml中的foreach 标签。ForEachSqlNode 内属性分别对应标签上的各属性。通过内部解析器ExpressionEvaluator将collect中指定的属性的值取出(采用OGNL方式) |
|
Session
DefaultSession
为默认实现类
该类中有个比较重要的包装参数的方法:wrapCollection
。对于Collection类型和数组类型的参数,会给转为Map,且key分别为list
和array
。
总结
通过整理每个包的主要功能。通览整个mybatis的代码结构,了解各个组件的位置和大概的处理关系。为后续分析源码打下基础。
可能的问题
动态Sql每次请求都要重新解析一次,可能每次传入的参数不同,解析也就不同。
StatementHandler每个Session都需要重新建立实例
版权声明:本文由 在 2019年04月30日发表。本文采用CC BY-NC-SA 4.0许可协议,非商业转载请注明出处,不得用于商业目的。
文章题目及链接:《Mybatis源码分析(1) - Mybatis关键类》