精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

我們一起聊聊 MyBatis 動態 SQL 原理

開發 前端
SqlSessionFactoryBean實現了Spring的InitializingBean接口,InitializingBean接口的afterPropertiesSet方法中會調用buildSqlSessionFactory方法 該方法內部會使用XMLConfigBuilder解析屬性configLocation中配置的路徑,還會使用XMLMapperBuilder屬性解析mapperLoc

引入

我們在使用mybatis的時候,會在xml中編寫sql語句。比如這段動態sql代碼:

<update id="update" parameterType="org.format.dynamicproxy.mybatis.bean.User">
    UPDATE users
    <trim prefix="SET" prefixOverrides=",">
        <if test="name != null and name != ''">
            name = #{name}
        </if>
        <if test="age != null and age != ''">
            , age = #{age}
        </if>
        <if test="birthday != null and birthday != ''">
            , birthday = #{birthday}
        </if>
    </trim>
    where id = ${id}
</update>

mybatis底層是如何構造這段sql的?

關于動態SQL的接口和類

SqlNode接口,簡單理解就是xml中的每個標簽,比如上述sql的update,trim,if標簽:

public interface SqlNode {
    boolean apply(DynamicContext context);
}

圖片圖片

SqlSource Sql源接口,代表從xml文件或注解映射的sql內容,主要就是用于創建BoundSql,有實現類DynamicSqlSource(動態Sql源),StaticSqlSource(靜態Sql源)等:

public interface SqlSource {
    BoundSql getBoundSql(Object parameterObject);
}

圖片圖片

BoundSql類,封裝mybatis最終產生sql的類,包括sql語句,參數,參數源數據等參數:

圖片圖片

XNode,一個Dom API中的Node接口的擴展類:

圖片圖片

BaseBuilder接口及其實現類(屬性,方法省略了,大家有興趣的自己看),這些Builder的作用就是用于構造sql:

圖片圖片

下面我們簡單分析下其中4個Builder:

  • XMLConfigBuilder:解析mybatis中configLocation屬性中的全局xml文件,內部會使用XMLMapperBuilder解析各個xml文件。
  • XMLMapperBuilder:遍歷mybatis中mapperLocations屬性中的xml文件中每個節點的Builder,比如user.xml,內部會使用XMLStatementBuilder處理xml中的每個節點。
  • XMLStatementBuilder:解析xml文件中各個節點,比如select,insert,update,delete節點,內部會使用XMLScriptBuilder處理節點的sql部分,遍歷產生的數據會丟到Configuration的mappedStatements中。
  • XMLScriptBuilder:解析xml中各個節點sql部分的Builder。

LanguageDriver接口及其實現類(屬性,方法省略了,大家有興趣的自己看),該接口主要的作用就是構造sql:

圖片圖片

簡單分析下XMLLanguageDriver(處理xml中的sql,RawLanguageDriver處理靜態sql):XMLLanguageDriver內部會使用XMLScriptBuilder解析xml中的sql部分。

源碼分析

Spring與Mybatis整合的時候需要配置SqlSessionFactoryBean,該配置會加入數據源和mybatis xml配置文件路徑等信息:

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="configLocation" value="classpath:mybatisConfig.xml"/>
    <property name="mapperLocations" value="classpath*:org/format/dao/*.xml"/>
</bean>

我們就分析這一段配置背后的細節:

SqlSessionFactoryBean實現了Spring的InitializingBean接口,InitializingBean接口的afterPropertiesSet方法中會調用buildSqlSessionFactory方法 該方法內部會使用XMLConfigBuilder解析屬性configLocation中配置的路徑,還會使用XMLMapperBuilder屬性解析mapperLocations屬性中的各個xml文件。部分源碼如下:

圖片圖片

由于XMLConfigBuilder內部也是使用XMLMapperBuilder,我們就看看XMLMapperBuilder的解析細節:

圖片圖片

圖片圖片

我們關注一下,增刪改查節點的解析:

圖片圖片

XMLStatementBuilder的解析:

圖片圖片

默認會使用XMLLanguageDriver創建SqlSource(Configuration構造函數中設置)。

XMLLanguageDriver創建SqlSource:

圖片圖片

XMLScriptBuilder解析sql:

圖片圖片

得到SqlSource之后,會放到Configuration中,有了SqlSource,就能拿BoundSql了,BoundSql可以得到最終的sql。

實例分析

以下面的xml解析大概說下parseDynamicTags的解析過程:

<update id="update" parameterType="org.format.dynamicproxy.mybatis.bean.User">
    UPDATE users
    <trim prefix="SET" prefixOverrides=",">
        <if test="name != null and name != ''">
            name = #{name}
        </if>
        <if test="age != null and age != ''">
            , age = #{age}
        </if>
        <if test="birthday != null and birthday != ''">
            , birthday = #{birthday}
        </if>
    </trim>
    where id = ${id}
</update>

parseDynamicTags方法的返回值是一個List,也就是一個Sql節點集合。SqlNode本文一開始已經介紹,分析完解析過程之后會說一下各個SqlNode類型的作用。

首先根據update節點(Node)得到所有的子節點,分別是3個子節點:

  • 文本節點 \n UPDATE users
  • trim子節點 ...
  • 文本節點 \n where id = #

遍歷各個子節點:

  • 如果節點類型是文本或者CDATA,構造一個TextSqlNode或StaticTextSqlNode;
  • 如果節點類型是元素,說明該update節點是個動態sql,然后會使用NodeHandler處理各個類型的子節點。這里的NodeHandler是XMLScriptBuilder的一個內部接口,其實現類包括TrimHandler、WhereHandler、SetHandler、IfHandler、ChooseHandler等。看類名也就明白了這個Handler的作用,比如我們分析的trim節點,對應的是TrimHandler;if節點,對應的是IfHandler...這里子節點trim被TrimHandler處理,TrimHandler內部也使用parseDynamicTags方法解析節點。

遇到子節點是元素的話,重復以上步驟:

trim子節點內部有7個子節點,分別是文本節點、if節點、是文本節點、if節點、是文本節點、if節點、文本節點。文本節點跟之前一樣處理,if節點使用IfHandler處理。遍歷步驟如上所示,下面我們看下幾個Handler的實現細節。

IfHandler處理方法也是使用parseDynamicTags方法,然后加上if標簽必要的屬性:

private class IfHandler implements NodeHandler {
    public void handleNode(XNode nodeToHandle, List<SqlNode> targetContents) {
      List<SqlNode> contents = parseDynamicTags(nodeToHandle);
      MixedSqlNode mixedSqlNode = new MixedSqlNode(contents);
      String test = nodeToHandle.getStringAttribute("test");
      IfSqlNode ifSqlNode = new IfSqlNode(mixedSqlNode, test);
      targetContents.add(ifSqlNode);
    }
}

TrimHandler處理方法也是使用parseDynamicTags方法,然后加上trim標簽必要的屬性:

private class TrimHandler implements NodeHandler {
    public void handleNode(XNode nodeToHandle, List<SqlNode> targetContents) {
      List<SqlNode> contents = parseDynamicTags(nodeToHandle);
      MixedSqlNode mixedSqlNode = new MixedSqlNode(contents);
      String prefix = nodeToHandle.getStringAttribute("prefix");
      String prefixOverrides = nodeToHandle.getStringAttribute("prefixOverrides");
      String suffix = nodeToHandle.getStringAttribute("suffix");
      String suffixOverrides = nodeToHandle.getStringAttribute("suffixOverrides");
      TrimSqlNode trim = new TrimSqlNode(configuration, mixedSqlNode, prefix, prefixOverrides, suffix, suffixOverrides);
      targetContents.add(trim);
    }
}

以上update方法最終通過parseDynamicTags方法得到的SqlNode集合如下:

圖片圖片

trim節點:

圖片圖片

由于這個update方法是個動態節點,因此構造出了DynamicSqlSource。DynamicSqlSource內部就可以構造sql了:

圖片圖片

DynamicSqlSource內部的SqlNode屬性是一個MixedSqlNode。然后我們看看各個SqlNode實現類的apply方法。下面分析一下各個SqlNode實現類的apply方法實現:

MixedSqlNode:MixedSqlNode會遍歷調用內部各個sqlNode的apply方法。

public boolean apply(DynamicContext context) {
   for (SqlNode sqlNode : contents) {
     sqlNode.apply(context);
   }
   return true;
}

StaticTextSqlNode:直接append sql文本。

public boolean apply(DynamicContext context) {
   context.appendSql(text);
   return true;
}

IfSqlNode:這里的evaluator是一個ExpressionEvaluator類型的實例,內部使用了OGNL處理表達式邏輯。

public boolean apply(DynamicContext context) {
   if (evaluator.evaluateBoolean(test, context.getBindings())) {
     contents.apply(context);
     return true;
   }
   return false;
}

TrimSqlNode:

public boolean apply(DynamicContext context) {
    FilteredDynamicContext filteredDynamicContext = new FilteredDynamicContext(context);
    boolean result = contents.apply(filteredDynamicContext);
    filteredDynamicContext.applyAll();
    return result;
}

public void applyAll() {
    sqlBuffer = new StringBuilder(sqlBuffer.toString().trim());
    String trimmedUppercaseSql = sqlBuffer.toString().toUpperCase(Locale.ENGLISH);
    if (trimmedUppercaseSql.length() > 0) {
        applyPrefix(sqlBuffer, trimmedUppercaseSql);
        applySuffix(sqlBuffer, trimmedUppercaseSql);
    }
    delegate.appendSql(sqlBuffer.toString());
}

private void applyPrefix(StringBuilder sql, String trimmedUppercaseSql) {
    if (!prefixApplied) {
        prefixApplied = true;
        if (prefixesToOverride != null) {
            for (String toRemove : prefixesToOverride) {
                if (trimmedUppercaseSql.startsWith(toRemove)) {
                    sql.delete(0, toRemove.trim().length());
                    break;
                }
            }
        }
        if (prefix != null) {
            sql.insert(0, " ");
            sql.insert(0, prefix);
        }
   }
}

TrimSqlNode的apply方法也是調用屬性contents(一般都是MixedSqlNode)的apply方法,按照實例也就是7個SqlNode,都是StaticTextSqlNode和IfSqlNode。 最后會使用FilteredDynamicContext過濾掉prefix和suffix。

責任編輯:武曉燕 來源: seven97
相關推薦

2025-04-11 00:05:49

RPC底層分布式

2024-07-11 08:26:00

2024-12-10 00:00:25

2025-02-28 08:46:24

框架微服務架構

2023-06-30 08:18:51

敏捷開發模式

2023-08-10 08:28:46

網絡編程通信

2023-08-04 08:20:56

DockerfileDocker工具

2022-05-24 08:21:16

數據安全API

2023-09-10 21:42:31

2022-06-15 08:00:50

磁盤RedisRocketMQ

2024-02-20 21:34:16

循環GolangGo

2021-08-27 07:06:10

IOJava抽象

2023-10-26 08:38:43

SQL排名平分分區

2023-05-29 09:07:10

SQLpageSize主鍵

2023-05-09 08:24:11

JNA鏈接庫代碼

2023-11-07 08:13:53

分布式網絡

2024-07-26 09:47:28

2022-10-08 00:00:05

SQL機制結構

2022-02-23 08:41:58

NATIPv4IPv6

2022-09-22 08:06:29

計算機平板微信
點贊
收藏

51CTO技術棧公眾號

中国一区二区三区| 日产精品99久久久久久| 国产视频精品视频| 韩日精品一区二区| 中文字幕在线不卡视频| 国产成人精品福利一区二区三区| 欧美videossex极品| 日韩精品一区二区久久| 日韩精品在线一区二区| 欧美黄网站在线观看| 黄色网在线播放| 成人免费福利片| 国产精品三级美女白浆呻吟 | 最新国产中文字幕| 这里只有精品在线| 亚洲视频一区二区三区| 91福利视频免费观看| 日韩av免费| 亚洲超丰满肉感bbw| 一区二区三区四区免费视频| 蜜臀av免费在线观看| 麻豆91小视频| 欧美孕妇性xx| 国产精品白嫩白嫩大学美女| 国产综合久久久| 精品国免费一区二区三区| 一区二区三区 欧美| 欧美日韩国产观看视频| 亚洲激情五月婷婷| 在线视频不卡国产| 国产福利在线视频| 91麻豆高清视频| 高清视频一区| 精品久久久中文字幕人妻| 美女在线观看视频一区二区| 欧美在线观看一区二区三区| 精品一区在线视频| 亚洲欧洲日韩| 日韩视频在线免费| 国产一区二区三区视频播放| 国产成人三级| 亚洲无限av看| 五月天精品视频| 日韩欧美在线精品| 亚洲福利小视频| 日本一区二区在线观看视频| 国产精品久久免费视频| 7799精品视频| 日韩免费高清在线| 成人自拍av| 色综合一区二区三区| 欧美 日韩 激情| 国产精品yjizz视频网| 亚洲午夜久久久| 国产精品一色哟哟| gratisvideos另类灌满| 亚洲国产精品久久艾草纯爱 | 一区二区毛片| 91av在线免费观看| 日本中文字幕久久| 日本成人在线不卡视频| 国产欧美一区二区三区在线| 中文字幕av资源| 久久99精品一区二区三区三区| 国产精品美女www| 亚洲最新av网站| 国产一区中文字幕| 97人人干人人| 少妇高潮一区二区三区99小说| 国产成人无遮挡在线视频| 9a蜜桃久久久久久免费| 日韩中文字幕免费观看| 91麻豆免费看片| 日本最新一区二区三区视频观看| 成人在线免费公开观看视频| 中文字幕一区在线观看| 轻点好疼好大好爽视频| 女厕盗摄一区二区三区| 日本福利一区二区| 又色又爽又黄视频| 都市激情久久| 一区二区日韩精品| 欧美做爰啪啪xxxⅹ性| 欧美天堂亚洲电影院在线观看 | 成人美女大片| 欧美日韩一区在线观看| 美女又黄又免费的视频| 日韩中文av| 精品国产拍在线观看| 免费在线视频观看| 免费久久99精品国产自在现线| 国产狼人综合免费视频| 国产综合视频在线| 国产女主播一区| 又大又硬又爽免费视频| 在线观看精品| 精品欧美乱码久久久久久| 免费人成又黄又爽又色| 亚洲欧美亚洲| 国产精品美女在线观看| 日本免费网站在线观看| 中文字幕精品三区| 男女视频网站在线观看| 色999韩欧美国产综合俺来也| 精品国产电影一区二区| 日本少妇aaa| 国产日韩欧美一区| 99久久免费国| 黄网址在线观看| 色哟哟日韩精品| 女同性αv亚洲女同志| 国产一区二区观看| 97在线视频观看| 国产99视频在线| 欧美国产一区二区在线观看 | 超免费在线视频| 欧美视频中文字幕| aa片在线观看视频在线播放| 欧美成人日韩| 国产精品亚洲综合天堂夜夜| 偷拍自拍在线| 亚洲一区视频在线观看视频| 在线观看岛国av| 青青草综合网| 日韩av电影国产| 午夜视频在线播放| 亚洲国产cao| 特种兵之深入敌后| 99久久精品费精品国产| 国产精品普通话| 美丽的姑娘在线观看免费动漫| 亚洲午夜视频在线观看| 性一交一黄一片| 一区二区日韩欧美| 国产一区视频在线| 香蕉视频在线播放| 欧美中文字幕一区| 午夜时刻免费入口| 天堂精品中文字幕在线| 麻豆亚洲一区| 美女100%一区| 亚洲一区二区久久| 欧美日韩 一区二区三区| 久久久久久久久久久久久久久99| 热99这里只有精品| 色老板在线视频一区二区| 韩国福利视频一区| 无码国产精品96久久久久| 激情成人中文字幕| 波多野结衣福利| 三级在线观看一区二区 | 黑人与亚洲人色ⅹvideos| 欧美视频一二三| 国产精品亚洲无码| 日韩精品国产欧美| 丝袜美腿玉足3d专区一区| 日韩一区二区三区在线免费观看| 国产一区二区三区18| 综合久久中文字幕| 国产精品传媒在线| 久久久福利影院| 亚洲夜间福利| 国产一区二区三区四区hd| 嗯~啊~轻一点视频日本在线观看| 亚洲第一网中文字幕| 午夜精品三级久久久有码| 久久综合九色综合97婷婷女人 | 亚洲偷熟乱区亚洲香蕉av| 亚洲性猛交富婆| 国产精品成人午夜| 国产精品嫩草69影院| 99精品免费| 日韩欧美亚洲在线| 成人精品视频在线观看| 久久久久国产精品www| 日韩偷拍自拍| 欧美日韩一级视频| 久久精品波多野结衣| 91亚洲精品久久久蜜桃网站| wwwwxxxx日韩| 国内精品福利| 日产中文字幕在线精品一区| 91精品亚洲一区在线观看| 国模精品视频一区二区三区| 国产在线高清| 日韩欧美第一区| 欧美一区二区三区四| 国产精品女人毛片| 9.1在线观看免费| 日韩国产精品大片| 欧美极品少妇无套实战| 视频一区中文| 91久久偷偷做嫩草影院| 国产日韩电影| 欧美区在线播放| 韩日视频在线| 亚洲风情亚aⅴ在线发布| 一区二区三区在线免费观看视频 | 蜜臀99久久精品久久久久小说| 1024亚洲合集| 国产精品成人一区二区三区电影毛片 | 中文字幕精品—区二区四季| 在线播放av网址| 免费成人在线观看视频| 免费毛片网站在线观看| 欧美岛国激情| 欧美精品亚洲| 精品福利网址导航| 91亚洲精品在线| 日本欧美日韩| 91精品国产高清自在线看超| h视频在线免费观看| 亚洲人成电影在线观看天堂色| www.五月婷婷| 91精品国产91久久久久久一区二区| 亚洲影院在线播放| 一区二区不卡在线播放| 在线视频这里只有精品| 久久久久一区二区三区四区| 亚洲一区二区三区黄色| 国内精品国产成人| 九九热精品在线播放| 久久精品日韩欧美| 国产中文字幕视频在线观看| 韩日在线一区| 91网站在线观看免费| 天天操夜夜操国产精品| 色播亚洲视频在线观看| 奇米狠狠一区二区三区| 国产一区二区久久久| 97一区二区国产好的精华液| 亚洲一区免费网站| av日韩在线免费观看| 成人av在线天堂| 另类一区二区三区| 国产精品日韩欧美大师| 99只有精品| 国产精品入口夜色视频大尺度| 欧美影视资讯| 国产精品大片wwwwww| 成人涩涩视频| 国产精品自拍网| 欧美激情不卡| 91久久精品美女高潮| 中文成人激情娱乐网| 国产日韩av在线播放| 中文成人在线| 99在线观看视频| 精品福利一区| 免费看成人片| 日韩av专区| 丰满女人性猛交| 欧美日韩调教| 国产妇女馒头高清泬20p多| 在线国产日韩| 情侣黄网站免费看| 日韩精品福利网| 污污网站免费看| 国产一二三精品| 久久无码专区国产精品s| 成人精品小蝌蚪| 7788色淫网站小说| 国产亚洲精品资源在线26u| a资源在线观看| 亚洲欧美电影院| 精品99久久久久成人网站免费| 亚洲高清在线视频| 久久精品视频1| 欧美午夜免费电影| a天堂在线观看视频| 亚洲第一二三四五区| 免费成人av电影| 精品国产欧美一区二区五十路| 女囚岛在线观看| 日韩暖暖在线视频| 不卡一区视频| 精品亚洲欧美日韩| 色一区二区三区四区| 99久久免费观看| 99视频精品| 亚洲色图 在线视频| 丰满少妇久久久久久久| 国产激情在线免费观看| 亚洲天堂中文字幕| 国产成人免费看| 欧美日韩二区三区| 色婷婷av一区二区三| 在线播放日韩精品| 高清在线视频不卡| 国产精品视频99| 丝袜久久网站| 穿情趣内衣被c到高潮视频| 国产一区二区三区久久久久久久久| 91香蕉视频导航| zzijzzij亚洲日本少妇熟睡| 日韩欧美黄色网址| 午夜精品福利在线| 97超碰资源站| 国产亚洲一区二区在线| 92久久精品| 亚洲一区二区三区乱码aⅴ蜜桃女| 五月激激激综合网色播| 成人在线观看毛片| 美女视频免费一区| 实拍女处破www免费看| 亚洲一区在线观看视频| 亚洲一卡二卡在线观看| 亚洲免费一在线| 波多野结衣精品| 成人字幕网zmw| 精品国产一区二区三区| 久久99中文字幕| 国产一区二区伦理片| 国产三级av在线播放| 亚洲成av人片一区二区梦乃| 国产深喉视频一区二区| 亚洲欧美日韩视频一区| 国产福利片在线观看| 99久久99久久| 午夜精品999| 在线视频日韩欧美| 国产精品免费视频网站| 日本久久综合网| 亚洲精品视频免费| 国产乱码午夜在线视频| 国产富婆一区二区三区| 欧美激情91| 少妇丰满尤物大尺度写真| 成人欧美一区二区三区黑人麻豆| 人人妻人人爽人人澡人人精品| 日韩成人中文字幕在线观看| 久草在线视频资源| 痴汉一区二区三区| 欧美日韩爆操| av电影中文字幕| 一区二区在线观看视频| 国产av无码专区亚洲av| 久久福利视频导航| 国产高清亚洲| 99热这里只有精品7| 国产一区二区免费看| 国产高潮国产高潮久久久91 | 久久国产精品亚洲人一区二区三区 | 亚洲免费视频一区二区三区| 国产欧美一区二区三区久久| 四虎成人精品永久免费av九九| 91亚洲免费视频| 国产精品白丝在线| 国产精品国产一区二区三区四区| 精品国产一区二区三区在线观看| 日韩午夜电影免费看| 一区二区三区偷拍| 国产剧情一区二区| 国产一级片免费观看| 亚洲国产成人久久综合| 美女高潮在线观看| 欧洲国产精品| 麻豆国产精品777777在线| 玖玖爱这里只有精品| 精品欧美乱码久久久久久1区2区| 欧美大胆a人体大胆做受| 欧美成ee人免费视频| 六月婷婷色综合| 日韩欧美中文字幕视频| 亚洲国产精品成人一区二区| 深夜av在线| 亚洲高清资源综合久久精品| 狠狠久久亚洲欧美| 国产大片中文字幕| 亚洲欧美自拍一区| 日韩毛片免费视频一级特黄| 一级性生活视频| 2020国产精品| 国产又粗又大又黄| 97久久久免费福利网址| 精品日韩欧美一区| 波多野结衣中文字幕在线播放| 亚洲高清免费观看高清完整版在线观看| 日本美女一级视频| 国产精品爽黄69| 伊人精品视频| 毛片aaaaaa| 欧美精品一区二区久久久| 精品成人免费一区二区在线播放| 欧美少妇在线观看| 久久综合久久综合亚洲| 国产精品久久久久久久免费看| 久久久久久久久久久免费精品 | 成人免费三级在线| 超碰在线97观看| 欧美激情乱人伦| 国产影视精品一区二区三区| 天堂va欧美va亚洲va老司机| 91久久精品午夜一区二区| 在线看一级片| 日韩一区二区电影在线观看| 成人午夜在线免费| 中文文字幕一区二区三三| 久久久在线视频| 亚洲深深色噜噜狠狠爱网站|