<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                > 文檔出自:[https://mybatis.org/mybatis-3/zh/dynamic-sql.html](https://mybatis.org/mybatis-3/zh/dynamic-sql.html) ## Mybatis專題三:動態SQL [TOC] 動態 SQL 是 MyBatis 的強大特性之一。如果你使用過 JDBC 或其它類似的框架,你應該能理解根據不同條件拼接 SQL 語句有多痛苦,例如拼接時要確保不能忘記添加必要的空格,還要注意去掉列表最后一個列名的逗號。利用動態 SQL,可以徹底擺脫這種痛苦。 使用動態 SQL 并非一件易事,但借助可用于任何 SQL 映射語句中的強大的動態 SQL 語言,MyBatis 顯著地提升了這一特性的易用性。 如果你之前用過 JSTL 或任何基于類 XML 語言的文本處理器,你對動態 SQL 元素可能會感覺似曾相識。在 MyBatis 之前的版本中,需要花時間了解大量的元素。借助功能強大的基于 OGNL 的表達式,MyBatis 3 替換了之前的大部分元素,大大精簡了元素種類,現在要學習的元素種類比原來的一半還要少。 * if * choose (when, otherwise) * trim (where, set) * foreach ### if 使用動態 SQL 最常見情景是根據條件包含 where 子句的一部分。比如: ~~~ <select id="findActiveBlogWithTitleLike" resultType="Blog"> SELECT * FROM BLOG WHERE state = ‘ACTIVE’ <if test="title != null"> AND title like #{title} </if> </select> ~~~ 這條語句提供了可選的查找文本功能。如果不傳入 “title”,那么所有處于 “ACTIVE” 狀態的 BLOG 都會返回;如果傳入了 “title” 參數,那么就會對 “title” 一列進行模糊查找并返回對應的 BLOG 結果(細心的讀者可能會發現,“title” 的參數值需要包含查找掩碼或通配符字符)。 如果希望通過 “title” 和 “author” 兩個參數進行可選搜索該怎么辦呢?首先,我想先將語句名稱修改成更名副其實的名稱;接下來,只需要加入另一個條件即可。 ~~~ <select id="findActiveBlogLike" resultType="Blog"> SELECT * FROM BLOG WHERE state = ‘ACTIVE’ <if test="title != null"> AND title like #{title} </if> <if test="author != null and author.name != null"> AND author_name like #{author.name} </if> </select> ~~~ ### choose、when、otherwise 有時候,我們不想使用所有的條件,而只是想從多個條件中選擇一個使用。針對這種情況,MyBatis 提供了 choose 元素,它有點像 Java 中的 switch 語句。 還是上面的例子,但是策略變為:傳入了 “title” 就按 “title” 查找,傳入了 “author” 就按 “author” 查找的情形。若兩者都沒有傳入,就返回標記為 featured 的 BLOG(這可能是管理員認為,與其返回大量的無意義隨機 Blog,還不如返回一些由管理員挑選的 Blog)。 ~~~ <select id="findActiveBlogLike" resultType="Blog"> SELECT * FROM BLOG WHERE state = ‘ACTIVE’ <choose> <when test="title != null"> AND title like #{title} </when> <when test="author != null and author.name != null"> AND author_name like #{author.name} </when> <otherwise> AND featured = 1 </otherwise> </choose> </select> ~~~ ### trim、where、set 前面幾個例子已經合宜地解決了一個臭名昭著的動態 SQL 問題。現在回到之前的 “if” 示例,這次我們將 “state = ‘ACTIVE’” 設置成動態條件,看看會發生什么。 ~~~ <select id="findActiveBlogLike" resultType="Blog"> SELECT * FROM BLOG WHERE <if test="state != null"> state = #{state} </if> <if test="title != null"> AND title like #{title} </if> <if test="author != null and author.name != null"> AND author_name like #{author.name} </if> </select> ~~~ 如果沒有匹配的條件會怎么樣?最終這條 SQL 會變成這樣: ~~~ SELECT * FROM BLOG WHERE ~~~ 這會導致查詢失敗。如果匹配的只是第二個條件又會怎樣?這條 SQL 會是這樣: ~~~ SELECT * FROM BLOG WHERE AND title like ‘someTitle’ ~~~ 這個查詢也會失敗。這個問題不能簡單地用條件元素來解決。這個問題是如此的難以解決,以至于解決過的人不會再想碰到這種問題。 MyBatis 有一個簡單且適合大多數場景的解決辦法。而在其他場景中,可以對其進行自定義以符合需求。而這,只需要一處簡單的改動: ~~~ <select id="findActiveBlogLike" resultType="Blog"> SELECT * FROM BLOG <where> <if test="state != null"> state = #{state} </if> <if test="title != null"> AND title like #{title} </if> <if test="author != null and author.name != null"> AND author_name like #{author.name} </if> </where> </select> ~~~ *where*元素只會在子元素返回任何內容的情況下才插入 “WHERE” 子句。而且,若子句的開頭為 “AND” 或 “OR”,*where*元素也會將它們去除。 如果*where*元素與你期望的不太一樣,你也可以通過自定義 trim 元素來定制*where*元素的功能。比如,和*where*元素等價的自定義 trim 元素為: ~~~ <trim prefix="WHERE" prefixOverrides="AND |OR "> ... </trim> ~~~ *prefixOverrides*屬性會忽略通過管道符分隔的文本序列(注意此例中的空格是必要的)。上述例子會移除所有*prefixOverrides*屬性中指定的內容,并且插入*prefix*屬性中指定的內容。 用于動態更新語句的類似解決方案叫做*set*。*set*元素可以用于動態包含需要更新的列,忽略其它不更新的列。比如: ~~~ <update id="updateAuthorIfNecessary"> update Author <set> <if test="username != null">username=#{username},</if> <if test="password != null">password=#{password},</if> <if test="email != null">email=#{email},</if> <if test="bio != null">bio=#{bio}</if> </set> where id=#{id} </update> ~~~ 這個例子中,*set*元素會動態地在行首插入 SET 關鍵字,并會刪掉額外的逗號(這些逗號是在使用條件語句給列賦值時引入的)。 來看看與*set*元素等價的自定義*trim*元素吧: ~~~ <trim prefix="SET" suffixOverrides=","> ... </trim> ~~~ 注意,我們覆蓋了后綴值設置,并且自定義了前綴值。 ### foreach 動態 SQL 的另一個常見使用場景是對集合進行遍歷(尤其是在構建 IN 條件語句的時候)。比如: ~~~ <select id="selectPostIn" resultType="domain.blog.Post"> SELECT * FROM POST P WHERE ID in <foreach item="item" index="index" collection="list" open="(" separator="," close=")"> #{item} </foreach> </select> ~~~ *foreach*元素的功能非常強大,它允許你指定一個集合,聲明可以在元素體內使用的集合項(item)和索引(index)變量。它也允許你指定開頭與結尾的字符串以及集合項迭代之間的分隔符。這個元素也不會錯誤地添加多余的分隔符,看它多智能! 提示你可以將任何可迭代對象(如 List、Set 等)、Map 對象或者數組對象作為集合參數傳遞給*foreach*。當使用可迭代對象或者數組時,index 是當前迭代的序號,item 的值是本次迭代獲取到的元素。當使用 Map 對象(或者 Map.Entry 對象的集合)時,index 是鍵,item 是值。 至此,我們已經完成了與 XML 配置及映射文件相關的討論。下一章將詳細探討 Java API,以便你能充分利用已經創建的映射配置。 ### script 要在帶注解的映射器接口類中使用動態 SQL,可以使用*script*元素。比如: ~~~ @Update({"<script>", "update Author", " <set>", " <if test='username != null'>username=#{username},</if>", " <if test='password != null'>password=#{password},</if>", " <if test='email != null'>email=#{email},</if>", " <if test='bio != null'>bio=#{bio}</if>", " </set>", "where id=#{id}", "</script>"}) void updateAuthorValues(Author author); ~~~ ### bind bind元素允許你在 OGNL 表達式以外創建一個變量,并將其綁定到當前的上下文。比如: ~~~ <select id="selectBlogsLike" resultType="Blog"> <bind name="pattern" value="'%' + _parameter.getTitle() + '%'" /> SELECT * FROM BLOG WHERE title LIKE #{pattern} </select> ~~~ ### 多數據庫支持 如果配置了 databaseIdProvider,你就可以在動態代碼中使用名為 “\_databaseId” 的變量來為不同的數據庫構建特定的語句。比如下面的例子: ~~~ <insert id="insert"> <selectKey keyProperty="id" resultType="int" order="BEFORE"> <if test="_databaseId == 'oracle'"> select seq_users.nextval from dual </if> <if test="_databaseId == 'db2'"> select nextval for seq_users from sysibm.sysdummy1" </if> </selectKey> insert into users values (#{id}, #{name}) </insert> ~~~ ### 動態 SQL 中的插入腳本語言 MyBatis 從 3.2 版本開始支持插入腳本語言,這允許你插入一種語言驅動,并基于這種語言來編寫動態 SQL 查詢語句。 可以通過實現以下接口來插入一種語言: ~~~ 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); } ~~~ 實現自定義語言驅動后,你就可以在 mybatis-config.xml 文件中將它設置為默認語言: ~~~ <typeAliases> <typeAlias type="org.sample.MyLanguageDriver" alias="myLanguage"/> </typeAliases> <settings> <setting name="defaultScriptingLanguage" value="myLanguage"/> </settings> ~~~ 或者,你也可以使用lang屬性為特定的語句指定語言: ~~~ <select id="selectBlog" lang="myLanguage"> SELECT * FROM BLOG </select> ~~~ 或者,在你的 mapper 接口上添加@Lang注解: ~~~ public interface Mapper { @Lang(MyLanguageDriver.class) @Select("SELECT * FROM BLOG") List<Blog> selectBlog(); } ~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看