mybatis源码阅读-MappedStatement各个属性解析过程(八)
调用方
类org.apache.ibatis.builder.xml.XMLMapperBuilder
private void configurationElement(XNode context) {
try {
String namespace = context.getStringAttribute("namespace");
if (namespace != null && !namespace.equals("")) {
this.builderAssistant.setCurrentNamespace(namespace);
this.cacheRefElement(context.evalNode("cache-ref"));
this.cacheElement(context.evalNode("cache"));
this.parameterMapElement(context.evalNodes("/mapper/parameterMap"));
this.resultMapElements(context.evalNodes("/mapper/resultMap"));
this.sqlElement(context.evalNodes("/mapper/sql"));
this.buildStatementFromContext(context.evalNodes("select|insert|update|delete"));
} else {
throw new BuilderException("Mapper's namespace cannot be empty");
}
} catch (Exception var3) {
throw new BuilderException("Error parsing Mapper XML. Cause: " + var3, var3);
}
}
解析ParameterMap
表现形式
<parameterMap class="com.ibatis.dataobject.Product" id="insert-product-param" >
<parameter property="id"/>
<parameter property="description"/>
<parameter property="price"/>
</parameterMap>
<statement id="insertProduct-useParaMap" parameterMap="insert-product-param">
<![CDATA[insert into t_product(prd_id,prd_description,prd_price) values(?,?,?)]]>
</statement>
源码
private void parameterMapElement(List<XNode> list) throws Exception {
Iterator i$ = list.iterator(); //循环解析所有ParameterMap
while(i$.hasNext()) {
XNode parameterMapNode = (XNode)i$.next();
String id = parameterMapNode.getStringAttribute("id");
String type = parameterMapNode.getStringAttribute("type");
Class<?> parameterClass = this.resolveClass(type);
List<XNode> parameterNodes = parameterMapNode.evalNodes("parameter");
List<ParameterMapping> parameterMappings = new ArrayList(); Iterator i$ = parameterNodes.iterator();
//解析里面的parameter节点封装成parameterMapping对象
while(i$.hasNext()) {
XNode parameterNode = (XNode)i$.next();
String property = parameterNode.getStringAttribute("property");
String javaType = parameterNode.getStringAttribute("javaType");
String jdbcType = parameterNode.getStringAttribute("jdbcType");
String resultMap = parameterNode.getStringAttribute("resultMap");
String mode = parameterNode.getStringAttribute("mode");
String typeHandler = parameterNode.getStringAttribute("typeHandler");
Integer numericScale = parameterNode.getIntAttribute("numericScale");
ParameterMode modeEnum = this.resolveParameterMode(mode);
Class<?> javaTypeClass = this.resolveClass(javaType);
JdbcType jdbcTypeEnum = this.resolveJdbcType(jdbcType);
Class<? extends TypeHandler<?>> typeHandlerClass = this.resolveClass(typeHandler);
ParameterMapping parameterMapping = this.builderAssistant.buildParameterMapping(parameterClass, property, javaTypeClass, jdbcTypeEnum, resultMap, modeEnum, typeHandlerClass, numericScale);
parameterMappings.add(parameterMapping);
}
//内部创建成ParameterMap对象 将parameterMappings设置到属性里面
this.builderAssistant.addParameterMap(id, parameterClass, parameterMappings);
} }
public ParameterMap addParameterMap(String id, Class<?> parameterClass, List<ParameterMapping> parameterMappings) {
id = this.applyCurrentNamespace(id, false);
//创建ParameterMap并添加到configuration
ParameterMap parameterMap = (new ParameterMap.Builder(this.configuration, id, parameterClass, parameterMappings)).build();
this.configuration.addParameterMap(parameterMap);
return parameterMap;
}
解析ResultMap
跟paramterMap解析很相似 但是resultMap有extend功能
表现形式
<resultMap id="simpleType" type="com.liqiang.entity.Classes">
<id property="id" column="id" /> </resultMap>
<resultMap id="studentMap" type="com.liqiang.entity.Classes" extends="simpleType">
<result property="name" column="name" />
</resultMap>
源码
private ResultMap resultMapElement(XNode resultMapNode, List<ResultMapping> additionalResultMappings) throws Exception {
ErrorContext.instance().activity("processing " + resultMapNode.getValueBasedIdentifier());
String id = resultMapNode.getStringAttribute("id", resultMapNode.getValueBasedIdentifier());
String type = resultMapNode.getStringAttribute("type", resultMapNode.getStringAttribute("ofType", resultMapNode.getStringAttribute("resultType", resultMapNode.getStringAttribute("javaType"))));
//判断是否有继承
String extend = resultMapNode.getStringAttribute("extends");
Boolean autoMapping = resultMapNode.getBooleanAttribute("autoMapping");
Class<?> typeClass = this.resolveClass(type);
Discriminator discriminator = null;
List<ResultMapping> resultMappings = new ArrayList();
resultMappings.addAll(additionalResultMappings);
List<XNode> resultChildren = resultMapNode.getChildren();
Iterator i$ = resultChildren.iterator(); while(i$.hasNext()) {
XNode resultChild = (XNode)i$.next();
if ("constructor".equals(resultChild.getName())) {
this.processConstructorElement(resultChild, typeClass, resultMappings);
} else if ("discriminator".equals(resultChild.getName())) {
discriminator = this.processDiscriminatorElement(resultChild, typeClass, resultMappings);
} else {
List<ResultFlag> flags = new ArrayList();
if ("id".equals(resultChild.getName())) {
flags.add(ResultFlag.ID);
} resultMappings.add(this.buildResultMappingFromContext(resultChild, typeClass, flags));
}
}
//内部会解析将extend的标签元素整合进来创建一个新的resultMap
ResultMapResolver resultMapResolver = new ResultMapResolver(this.builderAssistant, id, typeClass, extend, discriminator, resultMappings, autoMapping); try {
return resultMapResolver.resolve();
} catch (IncompleteElementException var14) {
this.configuration.addIncompleteResultMap(resultMapResolver);
throw var14;
}
}
解析"select|insert|update|delete"元素
public void parseStatementNode() {
String id = this.context.getStringAttribute("id");
String databaseId = this.context.getStringAttribute("databaseId");
if (this.databaseIdMatchesCurrent(id, databaseId, this.requiredDatabaseId)) {
Integer fetchSize = this.context.getIntAttribute("fetchSize");
Integer timeout = this.context.getIntAttribute("timeout");
String parameterMap = this.context.getStringAttribute("parameterMap");
String parameterType = this.context.getStringAttribute("parameterType");
Class<?> parameterTypeClass = this.resolveClass(parameterType);
String resultMap = this.context.getStringAttribute("resultMap");
String resultType = this.context.getStringAttribute("resultType");
String lang = this.context.getStringAttribute("lang");
LanguageDriver langDriver = this.getLanguageDriver(lang);
Class<?> resultTypeClass = this.resolveClass(resultType);
String resultSetType = this.context.getStringAttribute("resultSetType");
StatementType statementType = StatementType.valueOf(this.context.getStringAttribute("statementType", StatementType.PREPARED.toString()));
ResultSetType resultSetTypeEnum = this.resolveResultSetType(resultSetType);
String nodeName = this.context.getNode().getNodeName();
SqlCommandType sqlCommandType = SqlCommandType.valueOf(nodeName.toUpperCase(Locale.ENGLISH));
boolean isSelect = sqlCommandType == SqlCommandType.SELECT;
boolean flushCache = this.context.getBooleanAttribute("flushCache", !isSelect).booleanValue();
boolean useCache = this.context.getBooleanAttribute("useCache", isSelect).booleanValue();
boolean resultOrdered = this.context.getBooleanAttribute("resultOrdered", false).booleanValue();
XMLIncludeTransformer includeParser = new XMLIncludeTransformer(this.configuration, this.builderAssistant);
includeParser.applyIncludes(this.context.getNode());
this.processSelectKeyNodes(id, parameterTypeClass, langDriver);
SqlSource sqlSource = langDriver.createSqlSource(this.configuration, this.context, parameterTypeClass);
String resultSets = this.context.getStringAttribute("resultSets");
String keyProperty = this.context.getStringAttribute("keyProperty");
String keyColumn = this.context.getStringAttribute("keyColumn");
String keyStatementId = id + "!selectKey";
keyStatementId = this.builderAssistant.applyCurrentNamespace(keyStatementId, true);
Object keyGenerator;
if (this.configuration.hasKeyGenerator(keyStatementId)) {
keyGenerator = this.configuration.getKeyGenerator(keyStatementId);
} else {
keyGenerator = this.context.getBooleanAttribute("useGeneratedKeys", this.configuration.isUseGeneratedKeys() && SqlCommandType.INSERT.equals(sqlCommandType)).booleanValue() ? new Jdbc3KeyGenerator() : new NoKeyGenerator();
}
//最终根据namesppace+id为key封装成MappedStatement保存到Configuration
this.builderAssistant.addMappedStatement(id, sqlSource, statementType, sqlCommandType, fetchSize, timeout, parameterMap, parameterTypeClass, resultMap, resultTypeClass, resultSetTypeEnum, flushCache, useCache, resultOrdered, (KeyGenerator)keyGenerator, keyProperty, keyColumn, databaseId, langDriver, resultSets);
}
}
mybatis源码阅读-MappedStatement各个属性解析过程(八)的更多相关文章
- Mybatis源码阅读-配置文件及映射文件解析
Mybatis源码分析: 1.配置文件解析: 1.1源码阅读入口: org.apache.ibatis.builder.xml.XMLConfigBuilder.parse(); 功能:解析全局配置文 ...
- mybatis源码阅读-初始化六个工具(六)
六个基本工具图集 图片来源:https://my.oschina.net/zudajun/blog/668596 ObjectFactory 类图 接口定义 public interface Obje ...
- mybatis源码阅读-初始化过程(七)
说明 mybatis初始化过程 就是解析xml到封装成Configuration对象 供后续使用 SqlSessionFactoryBuilder 代码例子 SqlSessionFactoryBuil ...
- Mybatis源码阅读 之 玩转Executor
承接上篇博客, 本文探究MyBatis中的Executor, 如下图: 是Executor体系图 本片博客的目的就是探究如上图中从顶级接口Executor中拓展出来的各个子执行器的功能,以及进一步了解 ...
- mybatis源码分析之02配置文件解析
该篇正式开始学习mybatis的源码,本篇主要学习mybatis是如何加载配置文件mybatis-config.xml的, 先从测试代码入手. public class V1Test { public ...
- 浩哥解析MyBatis源码(十一)——Parsing解析模块之通用标记解析器(GenericTokenParser)与标记处理器(TokenHandler)
原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6724223.html 1.回顾 上面的几篇解析了类型模块,在MyBatis中类型模块包含的 ...
- mybatis源码阅读心得
第一天阅读源码及创建时序图.(第一次用prosson画时序图,挺丑..) 1. 调用 SqlSessionFactoryBuilder 对象的 build(inputStream) 方法: 2. ...
- mybatis源码阅读(动态代理)
这一篇文章主要是记录Mybatis的动态代理学习成果,如果对源码感兴趣,可以看一下上篇文章 https://www.cnblogs.com/ChoviWu/p/10118051.html 阅读本篇的 ...
- mybatis源码阅读-SqlSessionFactory和SqlSession(三)
说明 读了3遍:https://my.oschina.net/zudajun/blog/665956 现在统一整理成笔记 并跟着源码一行一行调试 统一整理起来 SqlSession 接口定义 publ ...
随机推荐
- JSP-Runoob:JSP 状态码
ylbtech-JSP-Runoob:JSP 状态码 1.返回顶部 1. SP HTTP 状态码 HTTP请求与HTTP响应的格式相近,都有着如下结构: 以状态行+CRLF(回车换行)开始 零行或多行 ...
- bzoj1833
http://www.lydsy.com/JudgeOnline/problem.php?id=1833 2.5个小时就花在这上面了... 水到200题了...然并卵,天天做水题有什么前途... #i ...
- IDEA Spark Streaming 操作(RDD队列流)
import org.apache.spark.SparkConf import org.apache.spark.rdd.RDD import org.apache.spark.streaming. ...
- Akka源码分析-Remote-位置透明
上一篇博客中,我们研究了remote模式下如何发消息给远程actor,其实无论如何,最终都是通过RemoteActorRef来发送消息的.另外官网也明确说明了,ActorRef是可以忽略网络位置的,这 ...
- Java使用Player播放mp3
大家平时闲了都会听听歌,散散心,于是很多人就问,在Java里边如何播放歌曲呢,唉,别说,在Java里边还真能歌曲,下面我为大家揭晓. 我们都知道Java里边做什么都需要对应的jar包,首先贴上mave ...
- 【洛谷3321_BZOJ3992】[SDOI2015]序列统计(原根_多项式)
题目: 洛谷3321 分析: 一个转化思路比较神(典型?)的题-- 一个比较显然的\(O(n^3)\)暴力是用\(f[i][j]\)表示选了\(i\)个数,当前积在模\(m\)意义下为\(j\)的方案 ...
- scrapy框架简介和基础应用(python爬虫)
一.什么是scrapy? scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架,非常出名,非常强悍,所谓的框架就是一个已经被集成了各种功能(高性能异步下载,队列,分布式,持久化等)的具有 ...
- Elasticsearch之CURL命令的UPDATE
对于,Elasticsearch之CURL命令的UPDATE包括局部更新和全部更新.可以去看我写的另一篇博客. Elasticsearch之更新(全部更新和局部更新) 总结: ES全部更新,使用PUT ...
- Sqoop 是什么?(二)
Sqoop 是传统数据库与 Hadoop 之间数据同步的工具,它是 Hadoop 发展到一定程度的必然产物,它主要解决的是传统数据库和Hadoop之间数据的迁移问题.Sqoop 是连接传统关系型数据库 ...
- MVC系列学习(零)-本次学习可能会遇到的问题汇总
1.命名空间"System.Web"中不存在类型或命名空间名称"Optimization"(是否缺少程序集引用?) 在 区域学习(十六),遇到了个错误,如下 解 ...