Mybatis源码研究之SqlSource

来源:互联网 发布:quickconnect 域名 编辑:程序博客网 时间:2024/04/28 15:39

Mybatis中少有的有注释的接口

1. SqlSource接口

/** * Represents the content of a mapped statement read from an XML file or an annotation.  * It creates the SQL that will be passed to the database out of the input parameter received from the user. *  * @author Clinton Begin */ // 以上注释就不作翻译了.public interface SqlSource {  BoundSql getBoundSql(Object parameterObject);}

2. 继承图

SqlSource    StaticSqlSource  //  SqlSource实例的直接构造者就是 SqlSourceBuilder, 而SqlSourceBuilder中的parse方法所返回的是StaticSqlSource实例.    RawSqlSource  //     ProviderSqlSource    DynamicSqlSource
  1. Mybatis中非常重要的MappedStatement类中就有一个sqlSource字段.

  2. SqlSource实例的直接构造者就是 SqlSourceBuilder, 而SqlSourceBuilder所返回的则是StaticSqlSource实例(SqlSource的实现者之一). 而SqlSource接口的其他三个实现者(RawSqlSource,DynamicSqlSource,ProviderSqlSource)无一例外地都重度依赖于SqlSourceBuilder.

  3. SqlSourceBuilder类也继承了BaseBuilder, 相比较继承自BaseBuilder的其他XMLXxx来说, 这个类在语义上相当突兀. XMLXxxx是我们读Mybatis源码时最先会接触到的代码, 它们就是负责解析配置文件的. 所以我们会顺理成章地猜测继承BaseBuilder来解析XML配置文件. 而SqlSourceBuilder是为了复用BaseBuilder的功能.
  4. DynamicSqlSource 里的主要逻辑, 参见 MyBatis源码研究之$和# 中的补充说明部分.

3. BoundSql接口

关于这个请参见本人的另外一篇博客
Mybatis源码研究之BoundSql

4. LanguageDriver接口

  1. 该接口也是构造返回 SqlSource 的方法.
  2. 而且其子类XMLLanguageDriver(这个类也是Mybatis默认使用的LanguageDriver实现者)中有个细节就是,其createSqlSource方法中的

    script = PropertyParser.parse(script, configuration.getVariables());

    这样一行代表着 如果编写的映射语句中如果有 ${ } 形式 会使用 configuration.getVariables() 中定义的变量预替换一次, 而且查看PropertyParser类中的内部子类VariableTokenHandler, 它只会换已有变量,对于没有的, 它会原样返回 : return "${" + content + "}";

5. SqlSourceBuilder

  1. 该类的确切位置是在org.apache.ibatis.builder.SqlSourceBuilder
  2. org.apache.ibatis作为Mybatis的根package,我们不需要关心这个.
  3. 作为Mybatis的顶级package之一的builder 主要负责的是对xml配置文件的解析工作,而作为其中一员的SqlSourceBuilder自然不能免俗。
    1. 首先看名字就知道它关联到了SqlSource接口;而这个SqlSource接口的唯一方法返回的是BoundSql
    2. 其次这个类唯一的public方法parse,一眼看上去就是根据程序员提供的原始的sql语句,以及其他几个参数; 来构建出最终的SqlSource.
  4. 在查找对其parse的调用时,我们可以看到DynamicSqlSource类中有对其的使用,而DynamicSqlSource正好就是实现了SqlSource接口.
    DynamicSqlSource实现的getBoundSql方法中,我们可以看到对于在Mybatis的xml书写时,为啥parameterType的内容被无视,就是因为其对parameter type的选择最终还是基于实际的parameterObject的实际类型.
  5. SqlSourceBuilder的内部类ParameterMappingTokenHandler的私有方法buildParameterMapping中我们可以看到
    1. 看名字就知道这个方法是用来构建一个ParameterMapping实例.而ParameterMapping类就是封装了程序员所书写的#{ }中的所有内容.
    2. #{ }中各种参数的相应处理
    3. 目前的可用的参数如下javaType,jdbcType,mode,numericScale,resultMap,typeHandler,jdbcTypeName
    4. 例子如下: #{middleInitial, mode=OUT, jdbcType=STRUCT, jdbcTypeName=MY_TYPE, resultMap=departmentResultMap}
    5. 对于这一部分,可以看看MyBatis官方文档中的 >>Mapper XML文件 >> Parameters小节.
    6. 所以可以猜测到: 这些属性只能在#{ },而不能在${ }中使用.

6. ParameterMapping

  1. 虽然在xml映射文件编写时不再推荐使用ParameterMapping. 但在ParameterMappingTokenHandler 的实现里, 依然会将每个 #{ } 里的内容解析为一个ParameterMapping 实例.
  2. 这里补充一句: 每个ParameterMapping 实例真正被使用的位置则是位于ParameterHandler接口唯一的实现者DefaultParameterHandler 中的setParameters方法中. 所以我们在使用JDBC编程时进行的PreparedStatement.setXXX 操作其实是在每个 TypeHandler<T> 接口的实现类中完成的.
//TypeHandler<T>的使用位置: `DefaultParameterHandler`类中的第77行 (Mybatis-3.2.2.jar)typeHandler.setParameter(ps, i + 1, value, jdbcType);  

7. ParameterExpression

SqlSourceBuilder的内部类ParameterMappingTokenHandler中,其parseParameterMapping方法中对ParameterExpression类的使用
1. 这个ParameterExpression类封装了对#{ }中内容的解析逻辑,
2. 而且其继承自HashMap<String, String>,所以可以将解析的结果以键值对的方法存储起来.
3. 外界对其的调用直接以Map的方式获取即可.
4. 所以在使用#{ }中的内容得到一个ParameterExpression实例之后, 就能直接使用Map接口提供的方法调取用户在#{ }设置的属性值了.

  1. http://www.open-open.com/lib/view/open1363572227609.html
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 手指关节杵肿了怎么办 骨关节退行性变怎么办 疼风脚趾肿了怎么办 痛风脚右侧肿了怎么办 痛风引起的脚肿怎么办 老人腰闪了该怎么办 腰闪了站不起来怎么办 又怕冷又爱上火怎么办 肝上多发小囊肿怎么办 5岁宝宝咳嗽厉害怎么办 5岁宝宝咳嗽有痰怎么办 生川乌外贴中毒怎么办 7个月宝宝流鼻涕怎么办 脸上皮肤毛孔粗大有黑头怎么办 嗓子长了个囊肿怎么办 食管胃粘膜异位怎么办 狗狗肿瘤破了怎么办 婴儿胃食道反流怎么办 小儿胃食道反流怎么办 放疗后咳嗽痰多怎么办 胃息肉是恶性的怎么办 老是胃疼,胃胀怎么办 吃完饭之后胃胀怎么办 胃痛胃胀怎么办能缓解 胃胀不消化怎么办快速解决 便秘肛裂了好痛怎么办 胃消化慢还便秘怎么办 11个月婴儿便秘怎么办 80多岁老人便秘怎么办 狗狗便秘拉不出来怎么办 2个月幼犬便秘怎么办 狗狗便秘怎么办吃什么 痔疮又痛又痒怎么办 痔疮肉球特别痒怎么办 长了个小痔疮怎么办 产后4天没大便怎么办 7个月孕妇痔疮怎么办 运动完恶心想吐怎么办 跑步后恶心想吐怎么办 肠子不蠕动严重便秘怎么办 怀孕八个月严重便秘怎么办