精品欧美一区二区三区在线观看 _久久久久国色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技術棧公眾號

欧美疯狂xxxx大交乱88av| 日韩亚洲欧美中文三级| 日韩欧美一区二区视频在线播放| 懂色av蜜臀av粉嫩av喷吹| 希岛爱理一区二区三区| 亚洲成人精品久久| 国产福利在线免费| www.综合| 亚洲欧洲综合另类| 欧美二区三区| 国产黄a三级三级看三级| 亚洲欧美日韩一区在线观看| 超碰cao国产精品一区二区| 新狼窝色av性久久久久久| 正在播放亚洲1区| 97人妻精品一区二区三区免费| 日本在线中文字幕一区二区三区| 一区二区三区不卡在线观看| 视频一区视频二区视频三区视频四区国产 | 欧美精品videos另类| 成人听书哪个软件好| 国产日韩欧美视频在线| 欧美h在线观看| 欧美日本一区二区视频在线观看| 亚洲香蕉成视频在线观看| 国产精品嫩草69影院| 欧洲精品久久久久毛片完整版| 狠狠躁夜夜躁人人爽超碰91| 久久人妻无码一区二区| 在线免费看黄网站| 久久精品在线免费观看| 国产手机精品在线| 亚洲第一免费视频| 国产传媒一区在线| 亚洲aⅴ日韩av电影在线观看| 久久久久久无码精品大片| 国产精品久久777777毛茸茸 | 成人黄视频在线观看| 久久综合资源网| 国产精品10p综合二区| 国产露脸国语对白在线| 免费xxxx性欧美18vr| 国产精品jizz在线观看麻豆| 国产情侣自拍av| 18成人免费观看视频| 欧美日韩国产成人高清视频| 日本黄色小说视频| 自产国语精品视频| 欧美男插女视频| 久久久无码一区二区三区| 亚洲91视频| 欧美www在线| 日本少妇高清视频| 国产专区一区| 91精品国产精品| 久久久久久久久影院| 一区二区三区精品视频在线观看| 性色av一区二区三区免费 | 色婷婷激情久久| 少妇高清精品毛片在线视频| 日韩欧美另类一区二区| 在线精品视频免费观看| 国产九九在线视频| 热久久久久久| 日韩欧美不卡在线观看视频| 日本人dh亚洲人ⅹxx| 成人av资源网址| 日韩精品在线视频观看| 国产123在线| 五月天久久777| 欧美床上激情在线观看| 久久精品美女视频| 视频一区中文字幕国产| 国产一区二区在线播放| www.四虎在线观看| 99久久99久久精品免费看蜜桃| 蜜桃视频在线观看成人| av天在线观看| 亚洲一线二线三线视频| 成熟丰满熟妇高潮xxxxx视频| 不卡一二三区| 7777精品伊人久久久大香线蕉经典版下载 | 翡翠波斯猫1977年美国| 丰满岳乱妇国产精品一区| 91亚洲精华国产精华精华液| 日本一区二区三区免费看| 免费黄色网址在线观看| 精品久久久久久亚洲国产300| 男人操女人免费| 国产高清视频一区二区| 亚洲精品福利免费在线观看| 99久久99久久精品免费看小说.| 97久久夜色精品国产| 韩日精品中文字幕| 在线观看毛片视频| 99久免费精品视频在线观看| 日韩亚洲不卡在线| 精品久久sese| 亚洲欧美国产高清va在线播放| 99re热视频这里只精品| 先锋影音日韩| 91破解版在线观看| 欧美精选在线播放| 国精产品一区一区三区免费视频| 四季av一区二区三区免费观看 | 国产成人精品视频免费| 亚洲全部视频| 91在线中文字幕| 欧洲毛片在线| 亚洲成人av一区二区| 成人日韩在线视频| 亚洲影院天堂中文av色| 欧美寡妇偷汉性猛交| 一二三区中文字幕| 久久综合九色综合97_久久久| 欧美一级特黄aaaaaa在线看片| 伊人网在线播放| 精品国产乱子伦一区| 国产性生活大片| 日韩黄色小视频| 精品久久精品久久| 678在线观看视频| 日韩欧美色综合网站| youjizz亚洲女人| 欧美亚洲免费| 久久99久久精品国产| 超碰在线中文字幕| 日韩女优电影在线观看| 熟女少妇a性色生活片毛片| 久久天堂精品| 欧美成人一区二区在线| 国产资源在线观看入口av| 精品剧情v国产在线观看在线| 日本一级特级毛片视频| 精品一区二区在线视频| 亚洲图片都市激情| 国产精品99| 中文字幕亚洲综合久久| 亚洲 小说区 图片区| 国产偷v国产偷v亚洲高清| 国产极品粉嫩福利姬萌白酱| 懂色av一区二区| 欧美极品少妇xxxxx| 朝桐光av在线一区二区三区| 综合久久国产九一剧情麻豆| 伊人免费视频二| 亚洲精品在线观看91| 亚洲综合在线小说| 欧美家庭影院| 亚洲精品国产免费| 国产黄色免费观看| 国产目拍亚洲精品99久久精品| 午夜视频在线瓜伦| 成人免费在线观看av| 国产女人精品视频| 黄网站在线播放| 欧美不卡一区二区| 天天操天天干视频| 久久久精品国产免费观看同学| 日本精品www| 精品国产一区二区三区噜噜噜| 国产精品久久久久久久av大片| 成人在线免费公开观看视频| 欧美日韩国产天堂| 欧美人与禽zozzo禽性配| 成年人国产精品| 亚洲爆乳无码专区| 手机亚洲手机国产手机日韩| 成人免费网站在线| 久操av在线| 亚洲精品日韩欧美| 91麻豆成人精品国产免费网站| 综合亚洲深深色噜噜狠狠网站| 制服.丝袜.亚洲.中文.综合懂| aa国产精品| 亚洲精品视频一区二区三区| 久久久国产精品入口麻豆| 久久人人爽人人| 国产黄在线播放| 欧美一区二区性放荡片| 欧美日韩一二三四区| 欧美激情一区在线观看| 日本泡妞xxxx免费视频软件| 久久精品伊人| 六月婷婷激情网| 西野翔中文久久精品字幕| 国产精品狼人色视频一区| 婷婷色在线播放| 亚洲欧美国产日韩天堂区| 国产绳艺sm调教室论坛| 欧美性猛交xxxx偷拍洗澡| 成人免费视频入口| 99精品一区二区| 天天干天天色天天干| 一本色道精品久久一区二区三区 | 91青青在线视频| 欧美精品一区二区三区一线天视频 | 综合在线一区| 日本不卡一区二区三区视频| 日本少妇精品亚洲第一区| 日本高清视频一区| 欧洲一区二区三区| 在线视频欧美性高潮| 人人妻人人澡人人爽人人欧美一区| 欧美主播一区二区三区| 日韩精品视频免费播放| **性色生活片久久毛片| 精品人妻互换一区二区三区| 国产一区二区不卡老阿姨| 日本三区在线观看| 99国产精品久久久久久久| 一区二区三区不卡在线| 偷拍亚洲色图| 国产欧美日韩一区| 亚洲免费一区三区| 国产一区二区在线免费视频| 欧美黑人粗大| 97在线看免费观看视频在线观看| 二区三区在线观看| 色悠悠久久久久| 男人的天堂在线免费视频| 精品剧情在线观看| 亚洲av无码乱码国产麻豆| 欧美日韩大陆一区二区| 无码人妻aⅴ一区二区三区有奶水| 亚洲一二三四在线观看| avove在线播放| 亚洲人成网站色在线观看| 久久视频一区二区三区| 久久婷婷久久一区二区三区| 97人妻精品一区二区三区免费| 国产一区免费电影| 国内自拍第二页| 久久99国产精品尤物| 日本a√在线观看| 日韩vs国产vs欧美| 精品久久久久久久无码| 天堂蜜桃一区二区三区| 国产视频一区二区视频| 老司机午夜精品视频| 国产精品人人妻人人爽人人牛| 久久成人免费| 国产情侣av自拍| 日韩av一区二区三区四区| mm1313亚洲国产精品无码试看| 欧美在线综合| 激情综合网俺也去| 日本不卡123| 日韩av在线中文| 国产一区二区三区视频在线播放| 亚洲欧美日韩三级| 国产一区二区三区精品欧美日韩一区二区三区 | 美国美女黄色片| 国产精品国产a级| 国产一二三区精品| 一区二区三区精品视频在线| 久久久久久久久久久久久久免费看 | 久久99蜜桃精品| 九九九久久久久久久| 成人夜色视频网站在线观看| 天天躁日日躁狠狠躁免费麻豆| 99精品视频在线播放观看| 四虎影成人精品a片| 国产精品久久久久9999吃药| 美女视频久久久| 亚洲一区二区三区激情| 国产午夜免费福利 | www.成人在线观看| 亚洲国产精品成人一区二区| 韩日视频在线| 久久久成人精品| 国产高清在线a视频大全 | www.国产com| 欧美日韩国产bt| 国产综合无码一区二区色蜜蜜| 亚洲福利视频网| 国产精品视频一区二区久久| 久久久精品2019中文字幕神马| 日本在线视频网址| 国产91精品最新在线播放| 成人在线日韩| 久久99精品久久久久久三级| 欧美高清在线| 国产精品无码av在线播放| 日本v片在线高清不卡在线观看| 男插女视频网站| 久久久精品影视| 久久国产精品波多野结衣| 一本久久综合亚洲鲁鲁五月天| 国产乱色精品成人免费视频| 日韩av在线网页| 亚洲区欧洲区| 国产精品av电影| a级日韩大片| 中文字幕一区二区三区最新| 日韩一级大片| 97人人模人人爽人人澡| 久久人人97超碰com| 清纯粉嫩极品夜夜嗨av| 91黄色小视频| 蜜桃在线一区二区| 久久综合88中文色鬼| 桃色一区二区| 国产综合精品一区二区三区| 亚洲色图88| www日韩在线观看| 94色蜜桃网一区二区三区| 亚洲一级二级片| 欧美最猛性xxxxx直播| 天堂在线观看av| 九色精品美女在线| 丁香久久综合| 日本免费高清一区| 免费亚洲网站| 50一60岁老妇女毛片| 亚洲精品视频观看| 国产又大又黑又粗| 最近2019中文字幕mv免费看| 一本大道色婷婷在线| 国产另类自拍| 激情婷婷亚洲| 日本黄色www| √…a在线天堂一区| 制服丝袜在线一区| 亚洲日本aⅴ片在线观看香蕉| 999福利在线视频| 国产精品播放| 亚洲一级黄色| 丰满熟女人妻一区二区三区| 亚洲色图清纯唯美| 国产又黄又粗又长| 久久精品国亚洲| 91麻豆精品国产综合久久久 | 狠狠色狠狠色综合系列| 任你操精品视频| 精品视频在线免费看| av电影在线网| 国产精品视频yy9099| 日韩精品欧美| 在线观看岛国av| 国产精品美女久久久久久久久久久| 看黄色一级大片| 国产亚洲人成a一在线v站| free欧美| 亚洲精品国产精品久久| 久久超碰97中文字幕| 国产又粗又猛又爽又黄的视频小说 | 色视频www在线播放国产成人| 在线成人视屏| 一区二区日本| 国产成人一级电影| 日韩xxx高潮hd| 亚洲欧美日韩网| 日韩一区二区三区在线免费观看| 热舞福利精品大尺度视频| 日韩精品久久理论片| 奇米网一区二区| 日韩午夜在线观看| 成人影院在线播放| 欧美日韩精品免费看| 日韩激情中文字幕| 亚洲 欧美 变态 另类 综合| 日韩欧美在线影院| 国产精品一二三产区| 欧美一进一出视频| 久久99久久久欧美国产| 国产小视频在线看| 日韩精品黄色网| 国产69精品久久| 999一区二区三区| 久久嫩草精品久久久精品| 亚洲免费视频二区| 色综合天天综合网国产成人网 | 国产香蕉一区二区三区| 不卡电影免费在线播放一区| 91精品国产高清一区二区三密臀| 国产香蕉97碰碰久久人人| 国产精品国产亚洲精品| 国产精品成人久久电影| 国产欧美一区二区精品久导航| 一级黄色片免费| 51精品国产黑色丝袜高跟鞋| 成人精品视频| av电影在线播放| 欧美日韩国产另类一区| а√在线中文在线新版| 午夜久久资源| gogogo免费视频观看亚洲一| 中文字幕av久久爽| 91精品国产电影| 91精品国产自产在线观看永久∴| 欧美一区二区免费在线观看| 欧美午夜精品电影| 波多野结衣视频一区二区| 一本色道久久综合亚洲精品婷婷| www.欧美.com| 国产精品无码专区av免费播放| 全球成人中文在线| 欧美欧美全黄| 亚洲一二三四五六区|