对于mapper配置文件的解析是通过XMLMapperBuilder来完成的,其主要是解析结点为mapper下的结点

public void parse() {if (!configuration.isResourceLoaded(resource)) {configurationElement(parser.evalNode("/mapper"));configuration.addLoadedResource(resource);bindMapperForNamespace();}parsePendingResultMaps();parsePendingCacheRefs();parsePendingStatements();}private void configurationElement(XNode context) {try {String namespace = context.getStringAttribute("namespace");if (namespace == null || namespace.equals("")) {throw new BuilderException("Mapper's namespace cannot be empty");}builderAssistant.setCurrentNamespace(namespace);cacheRefElement(context.evalNode("cache-ref"));cacheElement(context.evalNode("cache"));parameterMapElement(context.evalNodes("/mapper/parameterMap"));resultMapElements(context.evalNodes("/mapper/resultMap"));sqlElement(context.evalNodes("/mapper/sql"));buildStatementFromContext(context.evalNodes("select|insert|update|delete"));} catch (Exception e) {throw new BuilderException("Error parsing Mapper XML. Cause: " + e, e);}}
1、解析cache-ref节点

设置当前缓存所引用的名字空间对应的缓存,相当于两个名字空间共用一个缓存,会在configuration中添加当前名字空间与引用名字空间的映射关系

private void cacheRefElement(XNode context) {if (context != null) {configuration.addCacheRef(builderAssistant.getCurrentNamespace(), context.getStringAttribute("namespace"));CacheRefResolver cacheRefResolver = new CacheRefResolver(builderAssistant, context.getStringAttribute("namespace"));try {cacheRefResolver.resolveCacheRef();} catch (IncompleteElementException e) {configuration.addIncompleteCacheRef(cacheRefResolver);}}}

2、解析cache节点

缓存的默认实现为PerpetualCache,默认淘汰策略为LRU,可以通过flushInterval设置定刷新间隔,size设置是修改Cache装饰器中有setSize方法的。 默认是readWrite为true的,即可序列化。默认blocking为非阻塞的。对于使用第三方缓存,可以通过属性子节点配置来设置。使用MapperBuilderAssistant来创建 Cache

private void cacheElement(XNode context) throws Exception {if (context != null) {String type = context.getStringAttribute("type", "PERPETUAL");Class<? extends Cache> typeClass = typeAliasRegistry.resolveAlias(type);String eviction = context.getStringAttribute("eviction", "LRU");Class<? extends Cache> evictionClass = typeAliasRegistry.resolveAlias(eviction);Long flushInterval = context.getLongAttribute("flushInterval");Integer size = context.getIntAttribute("size");boolean readWrite = !context.getBooleanAttribute("readOnly", false);boolean blocking = context.getBooleanAttribute("blocking", false);Properties props = context.getChildrenAsProperties();builderAssistant.useNewCache(typeClass, evictionClass, flushInterval, size, readWrite, blocking, props);}}public Cache useNewCache(Class<? extends Cache> typeClass,Class<? extends Cache> evictionClass,Long flushInterval,Integer size,boolean readWrite,boolean blocking,Properties props) {Cache cache = new CacheBuilder(currentNamespace).implementation(valueOrDefault(typeClass, PerpetualCache.class)).addDecorator(valueOrDefault(evictionClass, LruCache.class)).clearInterval(flushInterval).size(size).readWrite(readWrite).blocking(blocking).properties(props).build();configuration.addCache(cache);currentCache = cache;return cache;}

3、解析resultMap节点

resultMap会解析成ResultMap结构,对于没有嵌套结构的子项,会解析成ResultMapping结构。在解析时会解析三类,一类是constructor,一类是 discriminator、另外一类是id,result,association,collection,case。如果结点类型为association,collection,case并且属性中没有select,不会生成嵌套resultMap。如果指定了extend,在 resultMap解析时会先获取父类的resultMapping,然后删除子类中重写的父类的resultMapping。在resultMap没有指定id时,通过getValueBasedIdentifier来生成,生成规则为从根结点到当前结点路径来,结点名_[(id,value,property)属性名]拼接而成。如果属性名中有点,则用_替换。最后将 resultMap添加到 configuration中,添加到resultMaps时,会添加namespace+id和id两个对应的。StrictMap是继承HashMap,重写了put和get

discriminator结点属性及子结点

类型 名称
属性

column

javaType

jdbcType

typeHandler

子结点 case,其支持的属性有value, 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 = resolveClass(type);Discriminator discriminator = null;List<ResultMapping> resultMappings = new ArrayList<ResultMapping>();resultMappings.addAll(additionalResultMappings);List<XNode> resultChildren = resultMapNode.getChildren();for (XNode resultChild : resultChildren) {if ("constructor".equals(resultChild.getName())) {processConstructorElement(resultChild, typeClass, resultMappings);} else if ("discriminator".equals(resultChild.getName())) {discriminator = processDiscriminatorElement(resultChild, typeClass, resultMappings);} else {List<ResultFlag> flags = new ArrayList<ResultFlag>();if ("id".equals(resultChild.getName())) {flags.add(ResultFlag.ID);}resultMappings.add(buildResultMappingFromContext(resultChild, typeClass, flags));}}ResultMapResolver resultMapResolver = new ResultMapResolver(builderAssistant, id, typeClass, extend, discriminator, resultMappings, autoMapping);try {return resultMapResolver.resolve();} catch (IncompleteElementException  e) {configuration.addIncompleteResultMap(resultMapResolver);throw e;}}private ResultMapping buildResultMappingFromContext(XNode context, Class<?> resultType, List<ResultFlag> flags) throws Exception {String property;if (flags.contains(ResultFlag.CONSTRUCTOR)) {property = context.getStringAttribute("name");} else {property = context.getStringAttribute("property");}String column = context.getStringAttribute("column");String javaType = context.getStringAttribute("javaType");String jdbcType = context.getStringAttribute("jdbcType");String nestedSelect = context.getStringAttribute("select");String nestedResultMap = context.getStringAttribute("resultMap",processNestedResultMappings(context, Collections.<ResultMapping> emptyList()));String notNullColumn = context.getStringAttribute("notNullColumn");String columnPrefix = context.getStringAttribute("columnPrefix");String typeHandler = context.getStringAttribute("typeHandler");String resultSet = context.getStringAttribute("resultSet");String foreignColumn = context.getStringAttribute("foreignColumn");boolean lazy = "lazy".equals(context.getStringAttribute("fetchType", configuration.isLazyLoadingEnabled() ? "lazy" : "eager"));Class<?> javaTypeClass = resolveClass(javaType);@SuppressWarnings("unchecked")Class<? extends TypeHandler<?>> typeHandlerClass = (Class<? extends TypeHandler<?>>) resolveClass(typeHandler);JdbcType jdbcTypeEnum = resolveJdbcType(jdbcType);return builderAssistant.buildResultMapping(resultType, property, column, javaTypeClass, jdbcTypeEnum, nestedSelect, nestedResultMap, notNullColumn, columnPrefix, typeHandlerClass, flags, resultSet, foreignColumn, lazy);}private String processNestedResultMappings(XNode context, List<ResultMapping> resultMappings) throws Exception {if ("association".equals(context.getName())|| "collection".equals(context.getName())|| "case".equals(context.getName())) {if (context.getStringAttribute("select") == null) {ResultMap resultMap = resultMapElement(context, resultMappings);return resultMap.getId();}}return null;}public V put(String key, V value) {if (containsKey(key)) {throw new IllegalArgumentException(name + " already contains value for " + key);}if (key.contains(".")) {final String shortKey = getShortName(key);if (super.get(shortKey) == null) {super.put(shortKey, value);} else {super.put(shortKey, (V) new Ambiguity(shortKey));}}return super.put(key, value);}public V get(Object key) {V value = super.get(key);if (value == null) {throw new IllegalArgumentException(name + " does not contain value for " + key);}if (value instanceof Ambiguity) {throw new IllegalArgumentException(((Ambiguity) value).getSubject() + " is ambiguous in " + name+ " (try using the full name including the namespace, or rename one of the entries)");}return value;}
4、解析sql节点

解析sql片段,将其添加到sqlFragments中

private void sqlElement(List<XNode> list, String requiredDatabaseId) throws Exception {for (XNode context : list) {String databaseId = context.getStringAttribute("databaseId");String id = context.getStringAttribute("id");id = builderAssistant.applyCurrentNamespace(id, false);if (databaseIdMatchesCurrent(id, databaseId, requiredDatabaseId)) {sqlFragments.put(id, context);}}}
 
 
 
 
 

mybatis对mapper.xml的解析(一)相关推荐

  1. mybatis对mapper.xml的解析(三)

    mybatis中对语句的解析使用了组合模式,针对不同的sql结点处理抽象出了SqlNode.详细的设计图为 什么时候创建不同的SqlSource? 创建DynamicSqlSource情况: 在包含有 ...

  2. mybatis对mapper.xml的解析(二)

    对select,insert,update,delete的解析是通过buildStatementFromContext来完成的,具体的解析是XMLStatementBuilder来完成的. 支持的属性 ...

  3. Mybatis实现*mapper.xml热部署-分子级更新

    需求: 项目在开发阶段或是修复bug阶段,会有修改mybatis的mapper.xml的时候,修改一般情况都要重启才能生失效,如果是分布式项目重启有时会耗时很久,都是无尽的等待.如果频繁修改,那么时间 ...

  4. idea中 mybatis 的 mapper.xml 新建没有 头文件

    idea中 mybatis 的 mapper.xml 新建没有 头文件 解决步骤: 1.直接 settings 2.直接 选择 MybatisMapper 添加: <?xml version=& ...

  5. 扫描mybatis的mapper.xml

    扫描mybatis的mapper.xml 扫描mybatis的mapper.xml 扫描mybatis的mapper.xml <!-- 如果不添加此节点mybatis的mapper.xml文件都 ...

  6. sql server解析xml属性为表格_[Mybatis][基础支持层]mapper xml sql 解析

    该系列文章针对 Mybatis 3.5.1 版本 Mybatis 中 标签解析,主要是为了得到两大部分数据 1.Mapper.class 接口 2.SQL 执行语句,结果集映射关系等数据 在上一章中提 ...

  7. MyBatis中的Mapper.xml文件解析

    具体可以参见MyBatis中文开发文档:https://mybatis.org/mybatis-3/zh/sqlmap-xml.html 我所述的主要有常用的几个标签和属性 一.parameterTy ...

  8. Mybatis学习--Mapper.xml映射文件

    简介 Mapper.xml映射文件中定义了操作数据库的sql,每个sql是一个statement,映射文件是mybatis的核心. 映射文件中有很多属性,常用的就是parameterType(输入类型 ...

  9. mybatis的mapper.xml文件中含有中文注释时运行出错,mybatis配置优化和别名优化 mybatis配置之映射器说明

    记录一个发现的小问题,刚刚在UserMapper.xml文件中有一段中文注释掉的内容: <!-- <resultMap id="Usermap" type=" ...

最新文章

  1. numpy条件筛选的坑
  2. 怎么用线程刷新 tkinter 进度条_tkinter做一个简易提词板(2)
  3. OSX 10.8+下开启Web 共享 的方法
  4. 干净的停止tomcat/java应用程序
  5. git add 失效
  6. 南京大学计算机考研分数线2021,南京大学2021年硕士研究生复试基本分数线
  7. /var/log目录中Linux日志文件的功能详解
  8. linux大io引起cpu使用率偏高,系统负载高, 但CPU使用率和IO都非常低
  9. 购物车程序二(模拟了用户登录,限次数三次)
  10. 转载:日本动漫编年史
  11. 卡地亚计算机辅助设计,工程图纸电子版用什么软件看
  12. 联想电脑打不开摄像头
  13. python实现sorted函数_Python sorted函数及用法
  14. 密码学——变色龙哈希
  15. Qt 制作带农历的日历
  16. 老式十字锁自动碰锁,换锁芯
  17. ps、markman、cutterman下载地址
  18. ply文件格式详细说明
  19. Fedora 26 安装搜狗拼音输入法 sogoupinyin
  20. 解决ie8下background-size不兼容问题

热门文章

  1. codeforces 401D. Roman and Numbers 数位dp
  2. 支付宝的kill-ie
  3. Linux 线程与进程,以及通信
  4. Singleton、MultiThread、Lib——实现单实例无锁多线程安全API
  5. python 为什么每次代码运行时间不同-python – 气流在同一个dag的不同时间运行任......
  6. 自学编程是从python语言还是c语言开始-非计算机专业大学生想自学编程应该学C语言还是学Python?...
  7. 零基础学python多久可以工作-零基础学习python,要多久才可以学好并且找到工作?...
  8. 毕业设计 基于python的网络爬虫-基于python的网络爬虫
  9. python是不是特别垃圾-python垃圾回收机制
  10. python怎么学最快-python怎么快速自学?