参数解析
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关键类》