Mybatis-3.動態(tài)SQL語句

回顧第二章的實操會發(fā)現(xiàn)在查詢大于或小于某個價格的商品時要分成兩個方法去寫唇跨。有沒有什么辦法讓一個方法就可以判斷是大于殊橙、小于還是大于等于、小于等于等等俄精?有的,那就是動態(tài)SQL榕堰。

什么是動態(tài)SQL

動態(tài)SQL可以理解為一種“根據(jù)不同條件拼接sql語句”的一種機制竖慧。
動態(tài)SQL除了可以解決上面提到的問題還可以解決諸多問題,如:

  1. 如果數(shù)據(jù)為null則不讓這個數(shù)據(jù)參加sql語句的執(zhí)行
  2. 插入多條數(shù)據(jù)

<where>逆屡、<if>標簽

相當于where關鍵字圾旨,如果where標簽的值是空的,那么就不會生成where關鍵字魏蔗,否則會生成 where ...砍的。(該標簽也會自動生成前面的空格)如:

<select ...>
  select * from user
  <where><!--user和<where>標簽之間的空格由<where>生成-->
    <if test="id!=0">id=#{id} and</if>
    <if test="name!=null">name=#{name}</if>
  </where>
</select>

當參數(shù)id的值為空,name不為空時莺治,執(zhí)行sql語句select * from user where name=#{name}廓鞠,id不為空,name為空時谣旁,執(zhí)行語句select * from user where id=#{id}床佳,當兩者都不為空執(zhí)行select * from user where id=#{id} and name=#{name},當兩者都為空執(zhí)行select * from user榄审。
可以通過這兩個標簽來解決上面提到的比大小問題:

  1. 創(chuàng)建Mapper方法為List<Product> selectProductByPrice(String op,double value)砌们,其中,op為符號搁进,>為匹配大于value的浪感,<為匹配小于value的,>=為匹配大于等于value的饼问,<=為匹配小于等于value的影兽,=為匹配等于value的。
  2. 修改Mapper映射文件匆瓜,在文件中添加下面內容:
    <select id="selectProductByPrice" resultType="product">
        select * from Product
        <where>
            <if test='op=="&gt;".toString()'>
                price &gt; #{value}
            </if>
            <if test='op=="&lt;".toString()'>
                price &lt; #{value}
            </if>
            <if test='op=="&gt;=".toString()'>
                price &gt;= #{value}
            </if>
            <if test='op=="&lt;=".toString()'>
                price &lt;= #{value}
            </if>
            <if test="op=='='.toString()">
                price = #{value}
            </if>
        </where>
    </select>
    
  3. 編寫一個測試類來測試這個方法(略)

if比較字符串報NumberFormatException錯誤可以嘗試在字符串后添加.toString()

<set>和<trim>

<where>用來判斷赢笨,那么<set>就用來更新未蝌。用法:

<update ...>
  update user
  <set>
    <if test="username!=null and username!=' ' ">
      username=#{username},
    </if>
    <if test="pwd!=null and pwd!=' '">
      pwd=#{pwd},
    </if>
  </set>
  where id=#{id}
</update>

如果username不為空就修改username,pwd不為空就修改pwd茧妒,兩者都不為空就兩個都修改萧吠,兩者都為空,報錯桐筏。
為了解決報錯的問題可以使用<trim>

<update ...>
  update user
  <trim prefix="set" suffixOverrides=",">
    <if test="username!=null and username!=' ' ">
      username=#{username},
    </if>
    <if test="pwd!=null and pwd!=' '">
      pwd=#{pwd},
    </if>
  </trim>
  where id=#{id}
</update>

效果與<set>一樣纸型,只不過如果username和pwd都為空也不會報錯。
trim的prefix表示要添加的前綴梅忌,這里可以填where狰腌、set。
suffixOverrides表示要去掉的后綴牧氮,這段代碼中的','表示去掉最后一個逗號琼腔。
還有prefixOverrides表示要去掉的前綴,suffix表示要添加的后綴踱葛。

<choose>丹莲、<when>和<otherwise>

<choose>、<when>尸诽、<otherwise>類似于java中的switch甥材、case和default。所以它的作用也是判斷性含。和java中不同的是 洲赵,choose會比較多個when。
用法:

<select ...>
  select * from user
  <trim prefix="where" suffixOverwrites="and">
    <choose>
      <when test="username!=null and username!=' '">
        username=#{username} and
      </when>
      <when test="job!=null and job!=0">
        job=#{job} and
      </when>
      <otherwise>
        id={id}
      </otherwise>
    </choose>
  </trim>
</select>

當username不為空商蕴,查找username叠萍,job不為空查找job,兩者都不為空全都查找究恤,兩者都為空查找id俭令。

復雜查詢操作-<foreach>

在程序開發(fā)過程中需要實現(xiàn)“允許用戶插入多條數(shù)據(jù)”或者“允許用戶根據(jù)多個id查詢用戶”的功能。而正常的insert并不能完成這項工作部宿。foreach就可以解決這個問題抄腔。

<foreach>操作數(shù)組和List

<select ...>
  select * from user where id in
  <foreach collection="ids" item="i" open="(" separator="," close=")">#{i}</foreach>
</select>

foreach的collection屬性是參數(shù)中的數(shù)組或者List,item為數(shù)組或者List中的元素理张,open和end表示這些數(shù)組元素用什么包裹赫蛇,代碼中用的是()包裹,separator表示多個#{i}之間用什么分割雾叭。還有index屬性(代碼中未提及)表示當前元素在數(shù)組或List中的索引悟耘。
假如ids數(shù)組有元素[1,2,5]那么正確的sql語句是select * from user where id in ('1','2','5')
下面這個例子是插入多條數(shù)據(jù)的例子:

<insert ...>
  insert into user
  <trim prefix="values" suffixOverrides=",">
    <foreach collection="users" item="user" sparator=",">
      (default,#{user.name},#{user.age})
    </foreach>
  </trim>
</insert>

這里面,sparator就變成了多個(default,#{user.name},#{user.age})之間用什么分割织狐。這樣就實現(xiàn)插入多條數(shù)據(jù)了暂幼。
類似的還可以實現(xiàn)同時刪除多條數(shù)據(jù)筏勒。這里就不再介紹了。

<foreach>操作map

和數(shù)組以及List相似旺嬉,只不過管行,index中是map的key而item是對應key的值。而collection實際上是map中key的集合邪媳。比如:
<foreach collection="ids" item="val" index="key" sparator=";">#{key},#{val}
假設參數(shù) ids(Map類型)中是這樣的數(shù)據(jù):[<1,"張三">,<2,"李四">] ,那么結果是1,'張三';2,'李四';

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末捐顷,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子雨效,更是在濱河造成了極大的恐慌迅涮,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件徽龟,死亡現(xiàn)場離奇詭異叮姑,居然都是意外死亡,警方通過查閱死者的電腦和手機顿肺,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門戏溺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人屠尊,你說我怎么就攤上這事「剑” “怎么了讼昆?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長骚烧。 經(jīng)常有香客問我浸赫,道長,這世上最難降的妖魔是什么赃绊? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任既峡,我火速辦了婚禮,結果婚禮上碧查,老公的妹妹穿的比我還像新娘运敢。我一直安慰自己,他們只是感情好忠售,可當我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布传惠。 她就那樣靜靜地躺著,像睡著了一般稻扬。 火紅的嫁衣襯著肌膚如雪卦方。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天泰佳,我揣著相機與錄音盼砍,去河邊找鬼尘吗。 笑死,一個胖子當著我的面吹牛浇坐,可吹牛的內容都是我干的睬捶。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼吗跋,長吁一口氣:“原來是場噩夢啊……” “哼侧戴!你這毒婦竟也來了?” 一聲冷哼從身側響起跌宛,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤酗宋,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后疆拘,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蜕猫,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年哎迄,在試婚紗的時候發(fā)現(xiàn)自己被綠了回右。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡漱挚,死狀恐怖翔烁,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情旨涝,我是刑警寧澤蹬屹,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站白华,受9級特大地震影響慨默,放射性物質發(fā)生泄漏。R本人自食惡果不足惜弧腥,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一厦取、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧管搪,春花似錦虾攻、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至岁经,卻和暖如春朋沮,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工樊拓, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留纠亚,地道東北人。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓筋夏,卻偏偏與公主長得像蒂胞,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子条篷,可洞房花燭夜當晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內容