暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

[Mybatis]-[基础支持层]-mapper xml sql 解析

花好夜猿 2020-09-23
609

该系列文章针对 Mybatis 3.5.1 版本

Mybatis 中 <mappers>
标签解析,主要是为了得到两大部分数据

1、Mapper.class 接口

2、SQL 执行语句,结果集映射关系等数据

在上一章中提到了 Mapper.class 文件的解析,Mapper.class 是接口文件,该接口是发起SQl执行调用的 API 入口,所有相关的操作都在其代理类 MapperProxy
中完成。

在上一章中忽略了 Mapper.class
文件中 @Select
等 SQL 语句注解的解析,本次章节将和 xml 中的 sql 解析一起分析。


`<mapper>` 标签解析入口


来回顾一下,XMLConfigBuilder
解析时序简图,如下:

在时序图中 <mappers>
加载解析在 XMLConfigBuilder#mapperElement
中完成,相关解析代码如下:

如上述代码,针对 <mappers>
子标签的解析分为两种:扫包批量解析和单个文件解析。

而无论是扫包批量解析亦或者单个文件解析,都会对 xml 文件 和 class 文件进行解析处理。

上一章以单个文件解析为入口分析 Mapper.class
文件的加载。

并提到了单个文件 <mapper>
标签配置的三种属性:

  • resource

  • url

  • class

这三种属性的配置都会尝试解析 xml 中的数据和 Mapper.class 上的 @Select
等注解,而 resource  和 url 所配置的直接就是 xml 路径,加载了 xml 通过命名空间即可找到关联对应的 Mapper.class 进行解析。

而 class 配置,如果要找到对应的 xml 文件,需要按照既定的规约给 xml 文件命名,规约为:Mapper.class.getName()
+ .xml

本次 sql 相关解析以单个文件的 resource 配置解析为入口展开,对应的解析入口代码为


从代码中,能够知道完成 xml 文件解析的类为 XMLMapperBuilder
,而进行解析的入口方法为 XMLMapperBuilder#parse

来具体看看 XMLMapperBuilder#parse
XML 文件解析入口代码

如上述代码,解析入口职责也很清晰,对 xml 文件和 mapper  class 文件进行了解析。


下面分别进入到各自的方法中查看各自是如何进行 sql 解析的。


xml 文件解析


xml 文件解析代码入口方法 XMLMapperBuilder#configurationElement

相关代码如下:

在上述解析代码中,针对 xml 文件中的各种标签进行解析,如 <cache-ref>
<cache>
<resultMap>
<insert>
等。

解析后的结果会被存储到 Configuration
中,例如:

<cache>
解析后的结果存储在 Configuration
caches
属性中,该属性定义如下

/** 容器:存放 Mapper.xml 中的 <cache> 构建的 Cache **/
/** key:为 Mapper.xml 中的 namespace **/
protected final Map<String, Cache> caches = new StrictMap<>("Caches collection");

<resultMap>
解析后的结果存储在 Configuration
中的 resultMaps
属性中,该属性定义如下

/** 容器:存放 Mapper.xml 中的 <resultMap> 构建的 ResultMap 对象 **/
/** key 通常为:namespace + "." + id【<resultMap id=""> 中的id属性值】 **/
protected final Map<String, ResultMap> resultMaps = new StrictMap<>("Result Maps collection");

<select|insert|update|delete>
等标签的解析会由新的对象 XMLStatementBuilder
进行解析,解析后的结果存储在Configuration
中的 mappedStatements
属性中,该属性定义如下:

/** 容器:存放 Mapper.xml 文件中 <select|delete|update|insert> 标签的解析数据 **/
/** key = namespace + <select|delete|update|insert id=""> id 属性 = Mapper.java 全类名 + <select|delete|update|insert id=""> id 属性 **/
protected final Map<String, MappedStatement> mappedStatements = new StrictMap<MappedStatement>("Mapped Statements collection")
.conflictMessageProducer((savedValue, targetValue) ->
". please check " + savedValue.getResource() + " and " + targetValue.getResource());

针对 xml 文件的解析,都是解析 <xxx>
标签,然后根据解析信息构建对应的 Java 对象,最终把这些数据填充到 Configuration
对象属性中。

更多解析细节,自行翻阅相关源码


mapper class 绑定 xml 文件数据时,同时解析注解



在 mybatis 中,除了能够在 xml 文件中配置数据,如:sql数据通过 <select|insert|delete|update>
等标签,缓存通过 <cache>
标签进行配置,同样的这些配置信息也支持有注解配置,该注解配置可以配置在相应的 mapper class 文件中。

来看一个 mapper class 的文件定义,代码如下:

如上述代码 @Select
对应的xml文件中的 <select>
@CacheNamespace
对应 xml 文件中的 <cache>

更多配置,参考 mybatis 官网,或者 mybatis 源码

从语义上来说,注解配置和xml配置并没有区别,区别在于声明的方式,一个 xml 标签,一个java代码注解
区别还在于解析构建类的不同,xml 解析在
XMLStatementBuilder
中完成,注解解析在 MapperAnnotationBuilder
中完成。

来看一下注解解析代码 MapperAnnotationBuilder#parse

如上述代码,通过解析注解完成相关配置信息的读取,如:缓存配置,SQL等。

同样的相关解析后的数据和 xml 解析后的数据一样,并存储在 Configuration
对应的容器中。


总结


xml 文件关于 sql 的解析或者标签的解析和 mapper class 关于注解式sql等解析方式不同。

xml 中关于 sql 的解析,在 XMLStatementBuilder
中完成。

mapper class 中关于 sql 的解析在 MapperAnnotationBuilder
中完成。

虽然 xml 和 注解的配置形式不同,但是他们所表达语义是相同的,解析后对应的 java 对象结构也是相同,这些解析数据,会被存放在 Configuration
对象中。

<mappers>
标签解析完 xml 文件和关联的 mapper class 文件后,Mybaits 中 Configuration
对象内容如下:

End

文章转载自花好夜猿,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论