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

支持的属性有

名称 说明
id 语句id
databaseId

不处理语句情况

1、在配置文件中设置了databaseIdProvider,并且当前设置的databaseId与配置文件中不一致时

2、配置文件 中没有设置,当前设置了databaseId

3、配置文件中没有设置databaseIdProvider,当前没有设置databaseId,有当前id对应的MappedStatement的databaseId不等于null

flushCache 布尔值,如果没有设置情况下,如果是select语句,则默认为false,否则为true
useCache 布尔值,如果没有设置情况上,select语句默认是true,否则为false
resultOrdered 布尔值,没有设置时,默认是false
parameterType 设置语句请求参数类型,可以使用别名
lang 设置语言驱动器,默认是XMLLanguageDriver
selectKey 生成主键节点
useGeneratedKey 如果没有设置,使用全局配置及当前语句是不是插入语句 。如果为true,则使用Jdbc3KeyGenerator,否则使用NoKeyGenerator
statementType 没有设置时默认是PREPARE类型
fetchSize 在StatementHandler中使用,来设置获取大小。
timeout 在StatementHandler中设置语句的执行超时时间
parameterMap 参数映射,已经不推荐使用
resultType 一种特殊的resultMap
resultMap 与resultType相当,两者二选一
resultSetType 用于在StatementHandler中设置语句的ResultType的类型
keyProperty 用于设置主属性,有多个属性时,用逗号分隔。用于KeyGenerator
keyColumn 用于设置数据库字段主键,有多个时,用逗号分隔。用于KeyGenerator以及用于StatementHandler初始化语句时
resultSets 有多个时,用逗号分隔。用于ResultSetHandler处理

selectKey支持的属性

名称 说明
databaseId

不处理语句情况

1、在配置文件中设置了databaseIdProvider,并且当前设置的databaseId与配置文件中不一致时

2、配置文件 中没有设置,当前设置了databaseId

3、配置文件中没有设置databaseIdProvider,当前没有设置databaseId,有当前id对应的MappedStatement的databaseId不等于null

resultType 返回的数据类型
statementType 如果没有设置,默认是PREPARE类型
keyProperty 主属性
keyColumn 数据库主键
order 在什么时候执行,没有设置时,默认是AFTER

1、解析语句中的include

XMLIncludeTransformer在解析include节点时,首先找到refid引用的节点,同时解析子节点property的name,value值对。接着在refid的引用的节点上应用applyIncludes递归调用。递归完后,用引用节点替换indlude节点。将引用节点的子结点添加到include之前,然后删除include节点。

在解析非include节点且节点类型是ELEMENT_NODE时,递归遍历子节点

如果解析的是引用节点,且节点是文本结点会作变量替换。

private void applyIncludes(Node source, final Properties variablesContext, boolean included) {if (source.getNodeName().equals("include")) {Node toInclude = findSqlFragment(getStringAttribute(source, "refid"), variablesContext);Properties toIncludeContext = getVariablesContext(source, variablesContext);applyIncludes(toInclude, toIncludeContext, true);if (toInclude.getOwnerDocument() != source.getOwnerDocument()) {toInclude = source.getOwnerDocument().importNode(toInclude, true);}source.getParentNode().replaceChild(toInclude, source);while (toInclude.hasChildNodes()) {toInclude.getParentNode().insertBefore(toInclude.getFirstChild(), toInclude);}toInclude.getParentNode().removeChild(toInclude);} else if (source.getNodeType() == Node.ELEMENT_NODE) {NodeList children = source.getChildNodes();for (int i = 0; i < children.getLength(); i++) {applyIncludes(children.item(i), variablesContext, included);}} else if (included && source.getNodeType() == Node.TEXT_NODE&& !variablesContext.isEmpty()) {// replace variables ins all text nodessource.setNodeValue(PropertyParser.parse(source.getNodeValue(), variablesContext));}}

2、解析selectKey节点

此结点在insert节点下,解析后添加到configuration中的keyGenerators中,添加后,删除selectKey节点

private void processSelectKeyNodes(String id, Class<?> parameterTypeClass, LanguageDriver langDriver) {List<XNode> selectKeyNodes = context.evalNodes("selectKey");if (configuration.getDatabaseId() != null) {parseSelectKeyNodes(id, selectKeyNodes, parameterTypeClass, langDriver, configuration.getDatabaseId());}parseSelectKeyNodes(id, selectKeyNodes, parameterTypeClass, langDriver, null);removeSelectKeyNodes(selectKeyNodes);}private void parseSelectKeyNodes(String parentId, List<XNode> list, Class<?> parameterTypeClass, LanguageDriver langDriver, String skRequiredDatabaseId) {for (XNode nodeToHandle : list) {String id = parentId + SelectKeyGenerator.SELECT_KEY_SUFFIX;String databaseId = nodeToHandle.getStringAttribute("databaseId");if (databaseIdMatchesCurrent(id, databaseId, skRequiredDatabaseId)) {parseSelectKeyNode(id, nodeToHandle, parameterTypeClass, langDriver, databaseId);}}}private void parseSelectKeyNode(String id, XNode nodeToHandle, Class<?> parameterTypeClass, LanguageDriver langDriver, String databaseId) {String resultType = nodeToHandle.getStringAttribute("resultType");Class<?> resultTypeClass = resolveClass(resultType);StatementType statementType = StatementType.valueOf(nodeToHandle.getStringAttribute("statementType", StatementType.PREPARED.toString()));String keyProperty = nodeToHandle.getStringAttribute("keyProperty");String keyColumn = nodeToHandle.getStringAttribute("keyColumn");boolean executeBefore = "BEFORE".equals(nodeToHandle.getStringAttribute("order", "AFTER"));//defaultsboolean useCache = false;boolean resultOrdered = false;KeyGenerator keyGenerator = NoKeyGenerator.INSTANCE;Integer fetchSize = null;Integer timeout = null;boolean flushCache = false;String parameterMap = null;String resultMap = null;ResultSetType resultSetTypeEnum = null;SqlSource sqlSource = langDriver.createSqlSource(configuration, nodeToHandle, parameterTypeClass);SqlCommandType sqlCommandType = SqlCommandType.SELECT;builderAssistant.addMappedStatement(id, sqlSource, statementType, sqlCommandType,fetchSize, timeout, parameterMap, parameterTypeClass, resultMap, resultTypeClass,resultSetTypeEnum, flushCache, useCache, resultOrdered,keyGenerator, keyProperty, keyColumn, databaseId, langDriver, null);id = builderAssistant.applyCurrentNamespace(id, false);MappedStatement keyStatement = configuration.getMappedStatement(id, false);configuration.addKeyGenerator(id, new SelectKeyGenerator(keyStatement, executeBefore));}private void removeSelectKeyNodes(List<XNode> selectKeyNodes) {for (XNode nodeToHandle : selectKeyNodes) {nodeToHandle.getParent().getNode().removeChild(nodeToHandle.getNode());}}

3、根据参数类型创建SqlSource

包含解析动态节点,创建DynamicSqlSource或者RawSqlSource

SqlSource sqlSource = langDriver.createSqlSource(configuration, context, parameterTypeClass);

4、创建MappedStatement,添加到Configuration中

//XMLStatementBuilder
builderAssistant.addMappedStatement(id, sqlSource, statementType, sqlCommandType,fetchSize, timeout, parameterMap, parameterTypeClass, resultMap, resultTypeClass,resultSetTypeEnum, flushCache, useCache, resultOrdered,keyGenerator, keyProperty, keyColumn, databaseId, langDriver, resultSets);//MappedBuilderAssistant
public MappedStatement addMappedStatement(String id,SqlSource sqlSource,StatementType statementType,SqlCommandType sqlCommandType,Integer fetchSize,Integer timeout,String parameterMap,Class<?> parameterType,String resultMap,Class<?> resultType,ResultSetType resultSetType,boolean flushCache,boolean useCache,boolean resultOrdered,KeyGenerator keyGenerator,String keyProperty,String keyColumn,String databaseId,LanguageDriver lang,String resultSets) {if (unresolvedCacheRef) {throw new IncompleteElementException("Cache-ref not yet resolved");}id = applyCurrentNamespace(id, false);boolean isSelect = sqlCommandType == SqlCommandType.SELECT;MappedStatement.Builder statementBuilder = new MappedStatement.Builder(configuration, id, sqlSource, sqlCommandType).resource(resource).fetchSize(fetchSize).timeout(timeout).statementType(statementType).keyGenerator(keyGenerator).keyProperty(keyProperty).keyColumn(keyColumn).databaseId(databaseId).lang(lang).resultOrdered(resultOrdered).resultSets(resultSets).resultMaps(getStatementResultMaps(resultMap, resultType, id)).resultSetType(resultSetType).flushCacheRequired(valueOrDefault(flushCache, !isSelect)).useCache(valueOrDefault(useCache, isSelect)).cache(currentCache);ParameterMap statementParameterMap = getStatementParameterMap(parameterMap, parameterType, id);if (statementParameterMap != null) {statementBuilder.parameterMap(statementParameterMap);}MappedStatement statement = statementBuilder.build();configuration.addMappedStatement(statement);return statement;}

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

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

    对于mapper配置文件的解析是通过XMLMapperBuilder来完成的,其主要是解析结点为mapper下的结点 public void parse() {if (!configuration.i ...

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

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

  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文件中含有中文注释时运行出错,mybatis配置优化和别名优化 mybatis配置之映射器说明

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

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

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

最新文章

  1. synchronized底层原理_你用过synchronized吗?它的底层原理是什么?Java经典面试题来了...
  2. php中处理xml文件的类 simpleXML
  3. 使用FragmentTabHost和ViewPager实现仿微信主界面侧滑
  4. layui table 分页 记住之前勾选的数据
  5. 一文看尽10篇目标检测最新论文(SpineNet/AugFPN/LRF-Net/SABL/DSFPN等)
  6. css3 box-shadow阴影(内外阴影与发光)讲解
  7. 计算机二级考试试题在线看,【TOP182015年全国计算机二级考试试题题库.doc文档免费在线阅读材料】...
  8. 大型网站架构系列:负载均衡详解(4)
  9. Shell多线程编程的实例
  10. 寒江独钓——win内核编程读书笔记-1
  11. hdu5258简单枚举
  12. IPsec简单实验-IKE协商
  13. 20190301 小中大
  14. C语言书籍阅读-读书笔记--《C专家编程》
  15. 什么是RS232电平?什么是TTL电平?
  16. 如何让函数只执行一次
  17. python虚拟串口_python 虚拟串口通信
  18. 微信朋友圈点赞测试用例
  19. 008 怎么取消隐藏文件扩展名
  20. Oracle10g卡顿,192MB内存运行win10 系统启动大约3分钟响应非常慢

热门文章

  1. LeetCode59 Spiral Matrix II
  2. ExtJS实现完美Grid(2)--分组统计
  3. RS-232串行口连接线 com口连接线 并口链接线 双绞线 交叉线 直连线
  4. 百度 php 图片文字识别,PHP实现百度OCR文字识别
  5. java list用法_java list的用法详解
  6. python怎么导入包-python模块之导入包及模块发布
  7. python是什么编程教程-python教程看完了,还是不会编程?
  8. python怎么导入视频-Python模块导入详解
  9. python27-python27安装
  10. python好学吗mooc中文网-Python的N种玩法_中国大学MOOC(慕课)