当前位置: 首页 > news >正文

网站建设多久可以学会优化的概念

网站建设多久可以学会,优化的概念,91手机用哪个浏览器,网站做二级站文章目录实例一、SqlSource处理入口二、SqlSource处理逻辑1、XMLScriptBuilder 构造方法2、解析动态sql3、DynamicSqlSource4、RawSqlSource解析sql&#xff08;1&#xff09;parse方法解析sql写在后面实例 此处我们分析的sql&#xff1a; <select id"selectBlog&quo…

文章目录

  • 实例
  • 一、SqlSource处理入口
  • 二、SqlSource处理逻辑
    • 1、XMLScriptBuilder 构造方法
    • 2、解析动态sql
    • 3、DynamicSqlSource
    • 4、RawSqlSource解析sql
      • (1)parse方法解析sql
  • 写在后面

实例

此处我们分析的sql:

<select id="selectBlog" resultType="com.demo.Blog" useCache="true">select * from blog where id = #{id}
</select>

一、SqlSource处理入口

在处理配置文件时,会处理Mapper.xml文件:

// org.apache.ibatis.builder.xml.XMLConfigBuilder#parseConfiguration
private void parseConfiguration(XNode root) {try {// issue #117 read properties firstpropertiesElement(root.evalNode("properties"));Properties settings = settingsAsProperties(root.evalNode("settings"));loadCustomVfs(settings);loadCustomLogImpl(settings);typeAliasesElement(root.evalNode("typeAliases"));pluginElement(root.evalNode("plugins"));objectFactoryElement(root.evalNode("objectFactory"));objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));reflectorFactoryElement(root.evalNode("reflectorFactory"));settingsElement(settings);// read it after objectFactory and objectWrapperFactory issue #631environmentsElement(root.evalNode("environments"));databaseIdProviderElement(root.evalNode("databaseIdProvider"));typeHandlerElement(root.evalNode("typeHandlers"));mapperElement(root.evalNode("mappers")); // 处理mapper标签} catch (Exception e) {throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);}
}// org.apache.ibatis.builder.xml.XMLConfigBuilder#mapperElement
private void mapperElement(XNode parent) throws Exception {if (parent != null) {for (XNode child : parent.getChildren()) {if ("package".equals(child.getName())) {String mapperPackage = child.getStringAttribute("name");configuration.addMappers(mapperPackage);} else {String resource = child.getStringAttribute("resource");String url = child.getStringAttribute("url");String mapperClass = child.getStringAttribute("class");if (resource != null && url == null && mapperClass == null) {ErrorContext.instance().resource(resource);try(InputStream inputStream = Resources.getResourceAsStream(resource)) {XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());mapperParser.parse();}} else if (resource == null && url != null && mapperClass == null) {ErrorContext.instance().resource(url);try(InputStream inputStream = Resources.getUrlAsStream(url)){XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, url, configuration.getSqlFragments());mapperParser.parse(); // 解析Mapper.xml}} else if (resource == null && url == null && mapperClass != null) {Class<?> mapperInterface = Resources.classForName(mapperClass);configuration.addMapper(mapperInterface);} else {throw new BuilderException("A mapper element may only specify a url, resource or class, but not more than one.");}}}}
}// org.apache.ibatis.builder.xml.XMLMapperBuilder#parse
public void parse() {if (!configuration.isResourceLoaded(resource)) {configurationElement(parser.evalNode("/mapper"));configuration.addLoadedResource(resource);bindMapperForNamespace();}parsePendingResultMaps();parsePendingCacheRefs();// 预处理StatementparsePendingStatements();
}// org.apache.ibatis.builder.xml.XMLMapperBuilder#parsePendingStatements
private void parsePendingStatements() {Collection<XMLStatementBuilder> incompleteStatements = configuration.getIncompleteStatements();synchronized (incompleteStatements) {Iterator<XMLStatementBuilder> iter = incompleteStatements.iterator();while (iter.hasNext()) {try {iter.next().parseStatementNode(); // 处理nodeiter.remove();} catch (IncompleteElementException e) {// Statement is still missing a resource...}}}
}
// org.apache.ibatis.builder.xml.XMLStatementBuilder#parseStatementNode
public void parseStatementNode() {String id = context.getStringAttribute("id");String databaseId = context.getStringAttribute("databaseId");if (!databaseIdMatchesCurrent(id, databaseId, this.requiredDatabaseId)) {return;}String nodeName = context.getNode().getNodeName();SqlCommandType sqlCommandType = SqlCommandType.valueOf(nodeName.toUpperCase(Locale.ENGLISH));boolean isSelect = sqlCommandType == SqlCommandType.SELECT;boolean flushCache = context.getBooleanAttribute("flushCache", !isSelect);boolean useCache = context.getBooleanAttribute("useCache", isSelect);boolean resultOrdered = context.getBooleanAttribute("resultOrdered", false);// Include Fragments before parsingXMLIncludeTransformer includeParser = new XMLIncludeTransformer(configuration, builderAssistant);includeParser.applyIncludes(context.getNode());String parameterType = context.getStringAttribute("parameterType");Class<?> parameterTypeClass = resolveClass(parameterType);String lang = context.getStringAttribute("lang");LanguageDriver langDriver = getLanguageDriver(lang);// Parse selectKey after includes and remove them.processSelectKeyNodes(id, parameterTypeClass, langDriver);// Parse the SQL (pre: <selectKey> and <include> were parsed and removed)KeyGenerator keyGenerator;String keyStatementId = id + SelectKeyGenerator.SELECT_KEY_SUFFIX;keyStatementId = builderAssistant.applyCurrentNamespace(keyStatementId, true);if (configuration.hasKeyGenerator(keyStatementId)) {keyGenerator = configuration.getKeyGenerator(keyStatementId);} else {keyGenerator = context.getBooleanAttribute("useGeneratedKeys",configuration.isUseGeneratedKeys() && SqlCommandType.INSERT.equals(sqlCommandType))? Jdbc3KeyGenerator.INSTANCE : NoKeyGenerator.INSTANCE;}// 创建SqlSource核心逻辑SqlSource sqlSource = langDriver.createSqlSource(configuration, context, parameterTypeClass);StatementType statementType = StatementType.valueOf(context.getStringAttribute("statementType", StatementType.PREPARED.toString()));Integer fetchSize = context.getIntAttribute("fetchSize");Integer timeout = context.getIntAttribute("timeout");String parameterMap = context.getStringAttribute("parameterMap");String resultType = context.getStringAttribute("resultType");Class<?> resultTypeClass = resolveClass(resultType);String resultMap = context.getStringAttribute("resultMap");String resultSetType = context.getStringAttribute("resultSetType");ResultSetType resultSetTypeEnum = resolveResultSetType(resultSetType);if (resultSetTypeEnum == null) {resultSetTypeEnum = configuration.getDefaultResultSetType();}String keyProperty = context.getStringAttribute("keyProperty");String keyColumn = context.getStringAttribute("keyColumn");String resultSets = context.getStringAttribute("resultSets");builderAssistant.addMappedStatement(id, sqlSource, statementType, sqlCommandType,fetchSize, timeout, parameterMap, parameterTypeClass, resultMap, resultTypeClass,resultSetTypeEnum, flushCache, useCache, resultOrdered,keyGenerator, keyProperty, keyColumn, databaseId, langDriver, resultSets);
}

我们找到了处理SqlSource的核心入口。

二、SqlSource处理逻辑

创建SqlSource,解析SQL,封装SQL语句(未参数绑定)和入参信息。

// org.apache.ibatis.scripting.xmltags.XMLLanguageDriver#createSqlSource(org.apache.ibatis.session.Configuration, org.apache.ibatis.parsing.XNode, java.lang.Class<?>)
@Override
public SqlSource createSqlSource(Configuration configuration, XNode script, Class<?> parameterType) {// 初始化了动态SQL标签处理器XMLScriptBuilder builder = new XMLScriptBuilder(configuration, script, parameterType);// 解析动态SQLreturn builder.parseScriptNode();
}

1、XMLScriptBuilder 构造方法

public XMLScriptBuilder(Configuration configuration, XNode context, Class<?> parameterType) {super(configuration);this.context = context;this.parameterType = parameterType;// 初始化动态SQL中的节点处理器集合initNodeHandlerMap();
}// 动态sql所有的节点
private void initNodeHandlerMap() {nodeHandlerMap.put("trim", new TrimHandler());nodeHandlerMap.put("where", new WhereHandler());nodeHandlerMap.put("set", new SetHandler());nodeHandlerMap.put("foreach", new ForEachHandler());nodeHandlerMap.put("if", new IfHandler());nodeHandlerMap.put("choose", new ChooseHandler());nodeHandlerMap.put("when", new IfHandler());nodeHandlerMap.put("otherwise", new OtherwiseHandler());nodeHandlerMap.put("bind", new BindHandler());
}

2、解析动态sql

XMLScriptBuilder#parseScriptNode用于解析动态sql:

public SqlSource parseScriptNode() {// 解析select\insert\ update\delete标签中的SQL语句,最终将解析到的SqlNode封装到MixedSqlNode中的List集合中// ****将带有${}号的SQL信息封装到TextSqlNode// ****将带有#{}号的SQL信息封装到StaticTextSqlNode// ****将动态SQL标签中的SQL信息分别封装到不同的SqlNode中MixedSqlNode rootSqlNode = parseDynamicTags(context);SqlSource sqlSource;if (isDynamic) {// 如果SQL中包含${}和动态SQL语句,则将SqlNode封装到DynamicSqlSource// 最终结果是:select id from blog where id = ${id}sqlSource = new DynamicSqlSource(configuration, rootSqlNode);} else {// 如果SQL中包含#{},则将SqlNode封装到RawSqlSource中,并指定parameterType// 最终的结果是:select id from blog where id = ?sqlSource = new RawSqlSource(configuration, rootSqlNode, parameterType);}return sqlSource;
}

parseDynamicTags解析sql语句:

解析select\insert\ update\delete标签中的SQL语句,最终将解析到的SqlNode封装到MixedSqlNode中的List集合中。

// org.apache.ibatis.scripting.xmltags.XMLScriptBuilder#parseDynamicTags
protected MixedSqlNode parseDynamicTags(XNode node) {List<SqlNode> contents = new ArrayList<>();//获取<select>\<insert>\<update>\<delete>4个标签的子节点,子节点包括元素节点和文本节点NodeList children = node.getNode().getChildNodes();for (int i = 0; i < children.getLength(); i++) {// 获取标签内的原始自定义sql:select * from blog where id = #{id}XNode child = node.newXNode(children.item(i));// 处理文本节点if (child.getNode().getNodeType() == Node.CDATA_SECTION_NODE || child.getNode().getNodeType() == Node.TEXT_NODE) {String data = child.getStringBody("");// 将文本内容封装到SqlNode中,还是原始sqlTextSqlNode textSqlNode = new TextSqlNode(data);// SQL语句中带有${}的话,就表示是dynamic的if (textSqlNode.isDynamic()) {contents.add(textSqlNode);isDynamic = true;} else {// SQL语句中(除了${}和下面的动态SQL标签),就表示是static的// StaticTextSqlNode的apply只是进行字符串的追加操作contents.add(new StaticTextSqlNode(data));}//处理元素节点} else if (child.getNode().getNodeType() == Node.ELEMENT_NODE) { // issue #628String nodeName = child.getNode().getNodeName();// 动态SQL标签处理器// 策略模式NodeHandler handler = nodeHandlerMap.get(nodeName);if (handler == null) {throw new BuilderException("Unknown element <" + nodeName + "> in SQL statement.");}handler.handleNode(child, contents);// 动态SQL标签是dynamic的isDynamic = true;}}return new MixedSqlNode(contents);
}

最终返回了携带了原始sql的对象。

3、DynamicSqlSource

如果SQL中包含${}和动态SQL语句,则将SqlNode封装到DynamicSqlSource。

咱们此处研究的是简单的、包含#{id}的sql,暂不研究动态SQL。

select id from blog where id = ${id}

比如说以上sql,会原封不动的生成SqlSource,并不会进行解析。

4、RawSqlSource解析sql

如果SQL中包含#{},则将SqlNode封装到RawSqlSource中,并指定parameterType

我们看一下RawSqlSource的构造方法:

public RawSqlSource(Configuration configuration, SqlNode rootSqlNode, Class<?> parameterType) {this(configuration, getSql(configuration, rootSqlNode), parameterType);
}public RawSqlSource(Configuration configuration, String sql, Class<?> parameterType) {// 解析SQL语句SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration);// 获取入参类型Class<?> clazz = parameterType == null ? Object.class : parameterType;// 开始解析sqlSource = sqlSourceParser.parse(sql, clazz, new HashMap<>());
}

(1)parse方法解析sql

// org.apache.ibatis.builder.SqlSourceBuilder#parse
public SqlSource parse(String originalSql, Class<?> parameterType, Map<String, Object> additionalParameters) {ParameterMappingTokenHandler handler = new ParameterMappingTokenHandler(configuration, parameterType, additionalParameters);// 创建分词解析器GenericTokenParser parser = new GenericTokenParser("#{", "}", handler);String sql;// 解析#{}if (configuration.isShrinkWhitespacesInSql()) {sql = parser.parse(removeExtraWhitespaces(originalSql)); // 处理额外的空格} else {sql = parser.parse(originalSql); // 解析,最终sql为select * from blog where id = ?}// 将解析之后的SQL信息,封装到StaticSqlSource对象中// SQL字符串是带有?号的字符串,?相关的参数信息,封装到ParameterMapping集合中return new StaticSqlSource(configuration, sql, handler.getParameterMappings());
}

调用GenericTokenParser的parse进行解析:

// org.apache.ibatis.parsing.GenericTokenParser#parse
public String parse(String text) {if (text == null || text.isEmpty()) {return "";}// search open tokenint start = text.indexOf(openToken);if (start == -1) {return text;}char[] src = text.toCharArray();int offset = 0;final StringBuilder builder = new StringBuilder();StringBuilder expression = null;do {if (start > 0 && src[start - 1] == '\\') {// this open token is escaped. remove the backslash and continue.builder.append(src, offset, start - offset - 1).append(openToken);offset = start + openToken.length();} else {// found open token. let's search close token.if (expression == null) {expression = new StringBuilder();} else {expression.setLength(0);}builder.append(src, offset, start - offset);offset = start + openToken.length();int end = text.indexOf(closeToken, offset);while (end > -1) {if (end > offset && src[end - 1] == '\\') {// this close token is escaped. remove the backslash and continue.expression.append(src, offset, end - offset - 1).append(closeToken);offset = end + closeToken.length();end = text.indexOf(closeToken, offset);} else {expression.append(src, offset, end - offset);break;}}if (end == -1) {// close token was not found.builder.append(src, start, src.length - start);offset = src.length;} else {builder.append(handler.handleToken(expression.toString())); // 该方法会返回一个 ? offset = end + closeToken.length();}}start = text.indexOf(openToken, offset);} while (start > -1);if (offset < src.length) {builder.append(src, offset, src.length - offset);}return builder.toString();
}

最终相当于是逐个字符进行解析,然后将#{id}替换成了 ?

写在后面

如果本文对你有帮助,请点赞收藏关注一下吧 ~
在这里插入图片描述

http://www.bjxfkj.com.cn/article/106698.html

相关文章:

  • 河南建设安全监督网站登封搜索引擎优化
  • 如何判断网站是用织梦做的seo推广方案怎么做
  • app 移动网站建设网站建设 网站制作
  • 国内外知名建设设计网站网络优化公司
  • 龙岗网站制作公司网站建设有哪些公司
  • 上海到北京多少公里上海seo公司哪个靠谱
  • 天涯武汉论坛冯耀宗seo
  • 烟台H5网站设计北京百度推广客服电话多少
  • 滕州网站设计衡阳seo优化
  • 加盟网站制作推广网络做推广广告公司
  • 网网站站建建站站企业网站设计毕业论文
  • 南京做电商网站的公司简介网络营销推广工作内容
  • 那种非法网站怎么做的微博热搜榜排名今日
  • 新开的公司建立网站有哪些要做的seo实训报告
  • 做网站推销的如何谈客户烟台百度推广公司
  • 有做浏览单的网站如何seo推广
  • 企业网站建设论坛营销课程培训都有哪些
  • 新云手机站官网开鲁视频
  • 网站如何做国外推广搜索引擎有哪些软件
  • 网站引流怎么做的网站建设纯免费官网
  • 做企业网站怎么收费的谷歌网站推广优化
  • wordpress资讯自媒体中文主题百度seo关键词怎么做
  • 水平b2b电子商务网站有哪些石家庄谷歌seo
  • 网站建设费用主要包括哪些内容西安网站seo服务
  • 珠海专门做网站seo论坛
  • 网站上的幻灯片如何做网站内容管理系统
  • 中国科技成就新闻深圳网站seo服务
  • windows7做网站如何发布自己的广告
  • 如何搭建自己的网址seo关键词外包公司
  • 怎么下载别人网站模板个人博客搭建