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"元素
org.apache.ibatis.builder.xml.XMLStatementBuilder#parseStatementNode
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); } }