衡阳派盒市场营销有限公司

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

一文掌握MyBatis的動(dòng)態(tài)SQL使用與原理

OSC開(kāi)源社區(qū) ? 來(lái)源:OSCHINA 社區(qū) ? 2023-01-06 11:27 ? 次閱讀

來(lái)源| OSCHINA 社區(qū)

作者 |華為云開(kāi)發(fā)者聯(lián)盟

摘要:使用動(dòng)態(tài) SQL 并非一件易事,但借助可用于任何 SQL 映射語(yǔ)句中的強(qiáng)大的動(dòng)態(tài) SQL 語(yǔ)言,MyBatis 顯著地提升了這一特性的易用性。

本文分享自華為云社區(qū)《MyBatis 詳解 - 動(dòng)態(tài) SQL 使用與原理》,作者:龍哥手記 。 動(dòng)態(tài) SQL 是 MyBatis 的強(qiáng)大特性之一。如果你使用過(guò) JDBC 或其它類(lèi)似的框架,你應(yīng)該能理解根據(jù)不同條件拼接 SQL 語(yǔ)句有多痛苦,例如拼接時(shí)要確保不能忘記添加必要的空格,還要注意去掉列表最后一個(gè)列名的逗號(hào)。利用動(dòng)態(tài) SQL,可以徹底擺脫這種痛苦。 使用動(dòng)態(tài) SQL 并非一件易事,但借助可用于任何 SQL 映射語(yǔ)句中的強(qiáng)大的動(dòng)態(tài) SQL 語(yǔ)言,MyBatis 顯著地提升了這一特性的易用性。 如果你之前用過(guò) JSTL 或任何基于類(lèi) XML 語(yǔ)言的文本處理器,你對(duì)動(dòng)態(tài) SQL 元素可能會(huì)感覺(jué)似曾相識(shí)。在 MyBatis 之前的版本中,需要花時(shí)間了解大量的元素。借助功能強(qiáng)大的基于 OGNL 的表達(dá)式,MyBatis 3 替換了之前的大部分元素,大大精簡(jiǎn)了元素種類(lèi),現(xiàn)在要學(xué)習(xí)的元素種類(lèi)比原來(lái)的一半還要少。

if

choose (when, otherwise)

trim (where, set)

foreach

if

使用動(dòng)態(tài) SQL 最常見(jiàn)情景是根據(jù)條件包含 where 子句的一部分。比如:

這條語(yǔ)句提供了可選的查找文本功能。如果不傳入 “title”,那么所有處于 “ACTIVE” 狀態(tài)的 BLOG 都會(huì)返回;如果傳入了 “title” 參數(shù),那么就會(huì)對(duì) “title” 一列進(jìn)行模糊查找并返回對(duì)應(yīng)的 BLOG 結(jié)果(細(xì)心的讀者可能會(huì)發(fā)現(xiàn),“title” 的參數(shù)值需要包含查找掩碼或通配符字符)。

如果希望通過(guò) “title” 和 “author” 兩個(gè)參數(shù)進(jìn)行可選搜索該怎么辦呢?首先,我想先將語(yǔ)句名稱(chēng)修改成更名副其實(shí)的名稱(chēng);接下來(lái),只需要加入另一個(gè)條件即可。

choose、when、otherwise

有時(shí)候,我們不想使用所有的條件,而只是想從多個(gè)條件中選擇一個(gè)使用。針對(duì)這種情況,MyBatis 提供了 choose 元素,它有點(diǎn)像 Java 中的 switch 語(yǔ)句。

還是上面的例子,但是策略變?yōu)椋簜魅肓?“title” 就按 “title” 查找,傳入了 “author” 就按 “author” 查找的情形。若兩者都沒(méi)有傳入,就返回標(biāo)記為 featured 的 BLOG(這可能是管理員認(rèn)為,與其返回大量的無(wú)意義隨機(jī) Blog,還不如返回一些由管理員挑選的 Blog)。

trim、where、set

前面幾個(gè)例子已經(jīng)合宜地解決了一個(gè)臭名昭著的動(dòng)態(tài) SQL 問(wèn)題。現(xiàn)在回到之前的 “if” 示例,這次我們將 “state = ‘ACTIVE’” 設(shè)置成動(dòng)態(tài)條件,看看會(huì)發(fā)生什么。

如果沒(méi)有匹配的條件會(huì)怎么樣?最終這條 SQL 會(huì)變成這樣:

SELECT * FROM BLOG
WHERE

這會(huì)導(dǎo)致查詢(xún)失敗。如果匹配的只是第二個(gè)條件又會(huì)怎樣?這條 SQL 會(huì)是這樣:

SELECT * FROM BLOG
WHERE
AND title like ‘someTitle’

這個(gè)查詢(xún)也會(huì)失敗。這個(gè)問(wèn)題不能簡(jiǎn)單地用條件元素來(lái)解決。這個(gè)問(wèn)題是如此的難以解決,以至于解決過(guò)的人不會(huì)再想碰到這種問(wèn)題。

MyBatis 有一個(gè)簡(jiǎn)單且適合大多數(shù)場(chǎng)景的解決辦法。而在其他場(chǎng)景中,可以對(duì)其進(jìn)行自定義以符合需求。而這,只需要一處簡(jiǎn)單的改動(dòng):

where 元素只會(huì)在子元素返回任何內(nèi)容的情況下才插入 “WHERE” 子句。而且,若子句的開(kāi)頭為 “AND” 或 “OR”,where 元素也會(huì)將它們?nèi)コ?/p>

如果 where 元素與你期望的不太一樣,你也可以通過(guò)自定義 trim 元素來(lái)定制 where 元素的功能。比如,和 where 元素等價(jià)的自定義 trim 元素為:


  ...

prefixOverrides 屬性會(huì)忽略通過(guò)管道符分隔的文本序列(注意此例中的空格是必要的)。上述例子會(huì)移除所有 prefixOverrides 屬性中指定的內(nèi)容,并且插入 prefix 屬性中指定的內(nèi)容。

用于動(dòng)態(tài)更新語(yǔ)句的類(lèi)似解決方案叫做 set。set 元素可以用于動(dòng)態(tài)包含需要更新的列,忽略其它不更新的列。比如:


  update Author
 
 username=#{username},
 password=#{password},
 email=#{email},
 bio=#{bio}
 
  where id=#{id}

這個(gè)例子中,set 元素會(huì)動(dòng)態(tài)地在行首插入 SET 關(guān)鍵字,并會(huì)刪掉額外的逗號(hào)(這些逗號(hào)是在使用條件語(yǔ)句給列賦值時(shí)引入的)。

來(lái)看看與 set 元素等價(jià)的自定義 trim 元素吧:


  ...

注意,我們覆蓋了后綴值設(shè)置,并且自定義了前綴值。

foreach

動(dòng)態(tài) SQL 的另一個(gè)常見(jiàn)使用場(chǎng)景是對(duì)集合進(jìn)行遍歷(尤其是在構(gòu)建 IN 條件語(yǔ)句的時(shí)候)。比如:

foreach 元素的功能非常強(qiáng)大,它允許你指定一個(gè)集合,聲明可以在元素體內(nèi)使用的集合項(xiàng)(item)和索引(index)變量。它也允許你指定開(kāi)頭與結(jié)尾的字符串以及集合項(xiàng)迭代之間的分隔符。這個(gè)元素也不會(huì)錯(cuò)誤地添加多余的分隔符,看它多智能!

提示:你可以將任何可迭代對(duì)象(如 List、Set 等)、Map 對(duì)象或者數(shù)組對(duì)象作為集合參數(shù)傳遞給 foreach。當(dāng)使用可迭代對(duì)象或者數(shù)組時(shí),index 是當(dāng)前迭代的序號(hào),item 的值是本次迭代獲取到的元素。當(dāng)使用 Map 對(duì)象(或者 Map.Entry 對(duì)象的集合)時(shí),index 是鍵,item 是值。

至此,我們已經(jīng)完成了與 XML 配置及映射文件相關(guān)的討論。下一章將詳細(xì)探討 Java API,以便你能充分利用已經(jīng)創(chuàng)建的映射配置。

script

要在帶注解的映射器接口類(lèi)中使用動(dòng)態(tài) SQL,可以使用 script 元素。比如:

 @Update({""})
 void updateAuthorValues(Author author);

bind

bind 元素允許你在 OGNL 表達(dá)式以外創(chuàng)建一個(gè)變量,并將其綁定到當(dāng)前的上下文。比如:

多數(shù)據(jù)庫(kù)支持

如果配置了 databaseIdProvider,你就可以在動(dòng)態(tài)代碼中使用名為 “_databaseId” 的變量來(lái)為不同的數(shù)據(jù)庫(kù)構(gòu)建特定的語(yǔ)句。比如下面的例子:


 
 
      select seq_users.nextval from dual
 
 
      select nextval for seq_users from sysibm.sysdummy1"
 
 
  insert into users values (#{id}, #{name})

動(dòng)態(tài) SQL 中的插入腳本語(yǔ)言

MyBatis 從 3.2 版本開(kāi)始支持插入腳本語(yǔ)言,這允許你插入一種語(yǔ)言驅(qū)動(dòng),并基于這種語(yǔ)言來(lái)編寫(xiě)動(dòng)態(tài) SQL 查詢(xún)語(yǔ)句。

可以通過(guò)實(shí)現(xiàn)以下接口來(lái)插入一種語(yǔ)言:

public interface LanguageDriver {
 ParameterHandler createParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql);
 SqlSource createSqlSource(Configuration configuration, XNode script, Class parameterType);
 SqlSource createSqlSource(Configuration configuration, String script, Class parameterType);
}

實(shí)現(xiàn)自定義語(yǔ)言驅(qū)動(dòng)后,你就可以在 mybatis-config.xml 文件中將它設(shè)置為默認(rèn)語(yǔ)言:


 


 

或者,你也可以使用 lang 屬性為特定的語(yǔ)句指定語(yǔ)言:

或者,在你的 mapper 接口上添加@Lang 注解:

public interface Mapper {
 @Lang(MyLanguageDriver.class)
 @Select("SELECT * FROM BLOG")
 List selectBlog();
}

提示:可以使用 Apache Velocity 作為動(dòng)態(tài)語(yǔ)言,更多細(xì)節(jié)請(qǐng)參考 MyBatis-Velocity 項(xiàng)目。

你前面看到的所有 xml 標(biāo)簽都由默認(rèn) MyBatis 語(yǔ)言提供,而它由語(yǔ)言驅(qū)動(dòng) org.apache.ibatis.scripting.xmltags.XmlLanguageDriver(別名為 xml)所提供。

動(dòng)態(tài) SQL 解析原理

我們?cè)谑褂?mybatis 的時(shí)候,會(huì)在 xml 中編寫(xiě) sql 語(yǔ)句。比如這段動(dòng)態(tài) sql 代碼:


    UPDATE users
 
 
            name = #{name}
 
 
            , age = #{age}
 
 
            , birthday = #{birthday}
 
 
    where id = ${id}

mybatis 底層是如何構(gòu)造這段 sql 的?下面帶著這個(gè)疑問(wèn),我們一步一步分析。

關(guān)于動(dòng)態(tài) SQL 的接口和類(lèi)

SqlNode 接口,簡(jiǎn)單理解就是 xml 中的每個(gè)標(biāo)簽,比如上述 sql 的 update,trim,if 標(biāo)簽:

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

d41aea24-8d2b-11ed-bfe3-dac502259ad0.png

SqlSource Sql 源接口,代表從 xml 文件或注解映射的 sql 內(nèi)容,主要就是用于創(chuàng)建 BoundSql,有實(shí)現(xiàn)類(lèi) DynamicSqlSource (動(dòng)態(tài) Sql 源),StaticSqlSource (靜態(tài) Sql 源) 等:

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

d42ae2d0-8d2b-11ed-bfe3-dac502259ad0.png

BoundSql 類(lèi),封裝 mybatis 最終產(chǎn)生 sql 的類(lèi),包括 sql 語(yǔ)句,參數(shù),參數(shù)源數(shù)據(jù)等參數(shù):

d435576a-8d2b-11ed-bfe3-dac502259ad0.png

XNode,一個(gè) Dom API 中的 Node 接口的擴(kuò)展類(lèi):

d43d7fa8-8d2b-11ed-bfe3-dac502259ad0.png

BaseBuilder 接口及其實(shí)現(xiàn)類(lèi) (屬性,方法省略了,大家有興趣的自己看), 這些 Builder 的作用就是用于構(gòu)造 sql:

d442c85a-8d2b-11ed-bfe3-dac502259ad0.png

下面我們簡(jiǎn)單分析下其中 4 個(gè) Builder:

XMLConfigBuilder:解析 mybatis 中 configLocation 屬性中的全局 xml 文件,內(nèi)部會(huì)使用 XMLMapperBuilder 解析各個(gè) xml 文件。

XMLMapperBuilder:遍歷 mybatis 中 mapperLocations 屬性中的 xml 文件中每個(gè)節(jié)點(diǎn)的 Builder,比如 user.xml,內(nèi)部會(huì)使用 XMLStatementBuilder 處理 xml 中的每個(gè)節(jié)點(diǎn)。

XMLStatementBuilder:解析 xml 文件中各個(gè)節(jié)點(diǎn),比如 select,insert,update,delete 節(jié)點(diǎn),內(nèi)部會(huì)使用 XMLScriptBuilder 處理節(jié)點(diǎn)的 sql 部分,遍歷產(chǎn)生的數(shù)據(jù)會(huì)丟到 Configuration 的 mappedStatements 中。

XMLScriptBuilder:解析 xml 中各個(gè)節(jié)點(diǎn) sql 部分的 Builder。

LanguageDriver 接口及其實(shí)現(xiàn)類(lèi) (屬性,方法省略了,大家有興趣的自己看),該接口主要的作用就是構(gòu)造 sql:

d448500e-8d2b-11ed-bfe3-dac502259ad0.png

簡(jiǎn)單分析下 XMLLanguageDriver (處理 xml 中的 sql,RawLanguageDriver 處理靜態(tài) sql):XMLLanguageDriver 內(nèi)部會(huì)使用 XMLScriptBuilder 解析 xml 中的 sql 部分。

源碼分析走起

Spring 與 Mybatis 整合的時(shí)候需要配置 SqlSessionFactoryBean,該配置會(huì)加入數(shù)據(jù)源和 mybatis xml 配置文件路徑等信息


 
 
 

我們就分析這一段配置背后的細(xì)節(jié):

SqlSessionFactoryBean 實(shí)現(xiàn)了 Spring 的 InitializingBean 接口,InitializingBean 接口的 afterPropertiesSet 方法中會(huì)調(diào)用 buildSqlSessionFactory 方法 該方法內(nèi)部會(huì)使用 XMLConfigBuilder 解析屬性 configLocation 中配置的路徑,還會(huì)使用 XMLMapperBuilder 屬性解析 mapperLocations 屬性中的各個(gè) xml 文件。部分源碼如下:

d44e590e-8d2b-11ed-bfe3-dac502259ad0.png

由于 XMLConfigBuilder 內(nèi)部也是使用 XMLMapperBuilder,我們就看看 XMLMapperBuilder 的解析細(xì)節(jié):

d4599116-8d2b-11ed-bfe3-dac502259ad0.png

d4617282-8d2b-11ed-bfe3-dac502259ad0.png

我們關(guān)注一下,增刪改查節(jié)點(diǎn)的解析:

d46c8942-8d2b-11ed-bfe3-dac502259ad0.png

XMLStatementBuilder 的解析:

d479221a-8d2b-11ed-bfe3-dac502259ad0.jpg

默認(rèn)會(huì)使用 XMLLanguageDriver 創(chuàng)建 SqlSource(Configuration 構(gòu)造函數(shù)中設(shè)置)。

XMLLanguageDriver 創(chuàng)建 SqlSource:

d47edca0-8d2b-11ed-bfe3-dac502259ad0.png

XMLScriptBuilder 解析 sql:

d487443a-8d2b-11ed-bfe3-dac502259ad0.png

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

實(shí)例分析

以下面的 xml 解析大概說(shuō)下 parseDynamicTags 的解析過(guò)程:


    UPDATE users
 
 
            name = #{name}
 
 
            , age = #{age}
 
 
            , birthday = #{birthday}
 
 
    where id = ${id}

parseDynamicTags 方法的返回值是一個(gè) List,也就是一個(gè) Sql 節(jié)點(diǎn)集合。SqlNode 本文一開(kāi)始已經(jīng)介紹,分析完解析過(guò)程之后會(huì)說(shuō)一下各個(gè) SqlNode 類(lèi)型的作用。

首先根據(jù) update 節(jié)點(diǎn) (Node) 得到所有的子節(jié)點(diǎn),分別是 3 個(gè)子節(jié)點(diǎn):

文本節(jié)點(diǎn) UPDATE users

trim 子節(jié)點(diǎn) ...

文本節(jié)點(diǎn) where id = #

遍歷各個(gè)子節(jié)點(diǎn):

如果節(jié)點(diǎn)類(lèi)型是文本或者 CDATA,構(gòu)造一個(gè) TextSqlNode 或 StaticTextSqlNode;

如果節(jié)點(diǎn)類(lèi)型是元素,說(shuō)明該 update 節(jié)點(diǎn)是個(gè)動(dòng)態(tài) sql,然后會(huì)使用 NodeHandler 處理各個(gè)類(lèi)型的子節(jié)點(diǎn)。這里的 NodeHandler 是 XMLScriptBuilder 的一個(gè)內(nèi)部接口,其實(shí)現(xiàn)類(lèi)包括 TrimHandler、WhereHandler、SetHandler、IfHandler、ChooseHandler 等。看類(lèi)名也就明白了這個(gè) Handler 的作用,比如我們分析的 trim 節(jié)點(diǎn),對(duì)應(yīng)的是 TrimHandler;if 節(jié)點(diǎn),對(duì)應(yīng)的是 IfHandler... 這里子節(jié)點(diǎn) trim 被 TrimHandler 處理,TrimHandler 內(nèi)部也使用 parseDynamicTags 方法解析節(jié)點(diǎn)。

遇到子節(jié)點(diǎn)是元素的話(huà),重復(fù)以上步驟:

trim 子節(jié)點(diǎn)內(nèi)部有 7 個(gè)子節(jié)點(diǎn),分別是文本節(jié)點(diǎn)、if 節(jié)點(diǎn)、是文本節(jié)點(diǎn)、if 節(jié)點(diǎn)、是文本節(jié)點(diǎn)、if 節(jié)點(diǎn)、文本節(jié)點(diǎn)。文本節(jié)點(diǎn)跟之前一樣處理,if 節(jié)點(diǎn)使用 IfHandler 處理。遍歷步驟如上所示,下面我們看下幾個(gè) Handler 的實(shí)現(xiàn)細(xì)節(jié)。

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

private class IfHandler implements NodeHandler {
 public void handleNode(XNode nodeToHandle, List targetContents) {
 List 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 標(biāo)簽必要的屬性:

private class TrimHandler implements NodeHandler {
 public void handleNode(XNode nodeToHandle, List targetContents) {
 List 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 方法最終通過(guò) parseDynamicTags 方法得到的 SqlNode 集合如下:

d48f7952-8d2b-11ed-bfe3-dac502259ad0.png

trim 節(jié)點(diǎn):

d49d45a0-8d2b-11ed-bfe3-dac502259ad0.png

由于這個(gè) update 方法是個(gè)動(dòng)態(tài)節(jié)點(diǎn),因此構(gòu)造出了 DynamicSqlSource。DynamicSqlSource 內(nèi)部就可以構(gòu)造 sql 了:

d4a82e16-8d2b-11ed-bfe3-dac502259ad0.png

DynamicSqlSource 內(nèi)部的 SqlNode 屬性是一個(gè) MixedSqlNode。然后我們看看各個(gè) SqlNode 實(shí)現(xiàn)類(lèi)的 apply 方法。下面分析一下各個(gè) SqlNode 實(shí)現(xiàn)類(lèi)的 apply 方法實(shí)現(xiàn):

MixedSqlNode:MixedSqlNode 會(huì)遍歷調(diào)用內(nèi)部各個(gè) 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 是一個(gè) ExpressionEvaluator 類(lèi)型的實(shí)例,內(nèi)部使用了 OGNL 處理表達(dá)式邏輯。

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 方法也是調(diào)用屬性 contents (一般都是 MixedSqlNode) 的 apply 方法,按照實(shí)例也就是 7 個(gè) SqlNode,都是 StaticTextSqlNode 和 IfSqlNode。最后會(huì)使用 FilteredDynamicContext 過(guò)濾掉 prefix 和 suffix。

審核編輯:湯梓紅

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 處理器
    +關(guān)注

    關(guān)注

    68

    文章

    19407

    瀏覽量

    231182
  • SQL
    SQL
    +關(guān)注

    關(guān)注

    1

    文章

    774

    瀏覽量

    44250
  • OGNL
    +關(guān)注

    關(guān)注

    0

    文章

    2

    瀏覽量

    1967
  • mybatis
    +關(guān)注

    關(guān)注

    0

    文章

    62

    瀏覽量

    6744

原文標(biāo)題:一文掌握 MyBatis 的動(dòng)態(tài) SQL 使用與原理

文章出處:【微信號(hào):OSC開(kāi)源社區(qū),微信公眾號(hào):OSC開(kāi)源社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    了解MyBatis的查詢(xún)?cè)?/a>

    本文通過(guò)MyBatis個(gè)低版本的bug(3.4.5之前的版本)入手,分析MyBatis次完整的查詢(xún)流程,從配置文件的解析到個(gè)查詢(xún)的完
    的頭像 發(fā)表于 10-10 11:42 ?1471次閱讀

    Mybatis的特點(diǎn)和核心配置文件

    Mybatis—01基礎(chǔ)&動(dòng)態(tài)SQL
    發(fā)表于 08-07 14:20

    為什么要動(dòng)態(tài)sql語(yǔ)句?

    為什么要動(dòng)態(tài)sql語(yǔ)句?因?yàn)?b class='flag-5'>動(dòng)態(tài)sql語(yǔ)句能夠提供些比較友好的機(jī)制1、可以使得些在編譯過(guò)程中
    發(fā)表于 12-20 06:00

    jdbc與mybatis的區(qū)別

    MyBatis款優(yōu)秀的持久層框架,它支持定制化 SQL、存儲(chǔ)過(guò)程以及高級(jí)映射。MyBatis 避免了幾乎所有的 JDBC 代碼和手動(dòng)設(shè)置參數(shù)以及獲取結(jié)果集。JDBC是
    發(fā)表于 02-02 17:43 ?1.1w次閱讀
    jdbc與<b class='flag-5'>mybatis</b>的區(qū)別

    mybatis是什么_MyBatis的優(yōu)缺點(diǎn)詳解_mybatis框架入門(mén)詳解

    Mybatis框架是別人開(kāi)發(fā)的種半成品軟件,可以用來(lái)通過(guò)定制輔助快速開(kāi)發(fā)是工具。MyBatis應(yīng)用程序根據(jù)XML配置文件創(chuàng)建SqlSessionFactory,SqlSessionFactory在
    發(fā)表于 02-24 09:16 ?2w次閱讀

    mybatis動(dòng)態(tài)sql詳解

    本文詳細(xì)介紹了mybatis執(zhí)行動(dòng)態(tài)sql語(yǔ)句的方法。
    發(fā)表于 02-24 11:37 ?3869次閱讀

    mybatis中#和$的區(qū)別

    注入。$方式無(wú)法防止Sql注入。$方式般用于傳入數(shù)據(jù)庫(kù)對(duì)象,例如傳入表名。般能用#的就別用$。所以我們?cè)谑褂?b class='flag-5'>mybatis的時(shí)候,盡量的使用#方式,這是大家要注意的地方。
    發(fā)表于 02-24 13:35 ?2295次閱讀

    在使用MyBatisSQL語(yǔ)句優(yōu)化總結(jié)

    MyBatis 作為款優(yōu)秀的持久層框架,它支持自定義SQL、存儲(chǔ)過(guò)程以及高級(jí)映射。它免除了幾乎所有的 JDBC 代碼以及設(shè)置參數(shù)和獲取結(jié)果集的工作。還可以通過(guò)簡(jiǎn)單的 XML 或注解來(lái)配置和映射原始
    的頭像 發(fā)表于 02-04 15:20 ?2837次閱讀

    Fluent Mybatis、原生MybatisMybatis Plus對(duì)比

    使用fluent mybatis可以不用寫(xiě)具體的xml文件,通過(guò)java api可以構(gòu)造出比較復(fù)雜的業(yè)務(wù)sql語(yǔ)句,做到代碼邏輯和sql邏輯的合。不再需要在Dao中組裝查詢(xún)或更新操作
    的頭像 發(fā)表于 09-15 15:41 ?1481次閱讀

    MybatisSQL注入審計(jì)的基本方法

    SQL注入漏洞作為WEB安全的最常見(jiàn)的漏洞之,在java中隨著預(yù)編譯與各種ORM框架的使用,注入問(wèn)題也越來(lái)越少。新手代碼審計(jì)者往往對(duì)Java Web應(yīng)用的多個(gè)框架組合而心生畏懼,不知如何下手,希望通過(guò)Mybatis框架使用不當(dāng)
    的頭像 發(fā)表于 10-17 11:16 ?1355次閱讀

    動(dòng)態(tài)Sql介紹

    動(dòng)態(tài)Sql介紹 動(dòng)態(tài) SQLMyBatis 的強(qiáng)大特性之。如果你使用過(guò) JDBC 或其它
    的頭像 發(fā)表于 05-31 09:34 ?1431次閱讀
    <b class='flag-5'>動(dòng)態(tài)</b><b class='flag-5'>Sql</b>介紹

    MyBatis動(dòng)態(tài)sql是什么?MyBatis動(dòng)態(tài)SQL最全教程

    動(dòng)態(tài) SQLMyBatis 的強(qiáng)大特性之。在 JDBC 或其它類(lèi)似的框架中,開(kāi)發(fā)人員通常需要手動(dòng)拼接 SQL 語(yǔ)句。根據(jù)不同的條件拼
    的頭像 發(fā)表于 08-10 10:18 ?1006次閱讀

    mybatis接口動(dòng)態(tài)代理原理

    MyBatis款輕量級(jí)的Java持久化框架,它通過(guò)XML或注解配置的方式,將數(shù)據(jù)庫(kù)操作與SQL語(yǔ)句解耦,提供了種簡(jiǎn)單、靈活的數(shù)據(jù)訪問(wèn)方式。在M
    的頭像 發(fā)表于 12-03 11:52 ?995次閱讀

    mybatis和mybatisplus的區(qū)別

    個(gè)輕量級(jí)的持久層框架,它提供了個(gè)靈活的SQL映射機(jī)制,使得開(kāi)發(fā)者可以編寫(xiě)原生SQL語(yǔ)句來(lái)操作數(shù)據(jù)庫(kù)。MyBatis的設(shè)計(jì)目標(biāo)是將原生SQL
    的頭像 發(fā)表于 12-03 11:53 ?2652次閱讀

    mybatis中$和井號(hào)區(qū)別

    MyBatis個(gè)開(kāi)源的Java持久層框架,它提供了許多強(qiáng)大的功能用于簡(jiǎn)化數(shù)據(jù)庫(kù)操作。在MyBatis中,我們可以使用兩種方式來(lái)動(dòng)態(tài)生成SQL
    的頭像 發(fā)表于 12-03 14:53 ?1033次閱讀
    普陀区| 大庆冠通棋牌下载| 百家乐官网出千大全| 老虎机派通娱乐| 百家乐官网网站那个诚信好| 澳门百家乐官网园游戏| 免费棋牌游戏| 百家乐游戏解码器| 贝博百家乐官网的玩法技巧和规则| 百家乐官网娱乐城体育| 大发888新澳博| 百家乐好赌吗| 百家乐官网园蒙| 百家乐官网AG| 太康县| 边城棋牌游戏下载| 百家乐百家乐技巧| 网上百家乐庄家有赌场优势吗| 射阳县| 百家乐赌场在线娱乐| 金榜百家乐官网的玩法技巧和规则| 挖掘百家乐官网赢钱秘籍| 立博网址| 喜力百家乐官网的玩法技巧和规则 | 百家乐官网优惠高的网址| 太子娱乐城开户| 大发888娱乐场金沙| 黄金城百家乐手机版| 百家乐赌场软件| 百家乐玩法教学视频| 黄金城百家乐官网手机用户| 988百家乐官网娱乐| 澳门百家乐官网线上娱乐城| 扎兰屯市| 网上真钱娱乐| 真人娱乐城排行榜| 大发888 娱乐网| 网络百家乐开户网| 百家乐乐翻天| 百家乐赌博器| 百家乐大路小路三珠路|