回顧第二章的實操會發(fā)現(xiàn)在查詢大于或小于某個價格的商品時要分成兩個方法去寫唇跨。有沒有什么辦法讓一個方法就可以判斷是大于殊橙、小于還是大于等于、小于等于等等俄精?有的,那就是動態(tài)SQL榕堰。
什么是動態(tài)SQL
動態(tài)SQL可以理解為一種“根據(jù)不同條件拼接sql語句”的一種機制竖慧。
動態(tài)SQL除了可以解決上面提到的問題還可以解決諸多問題,如:
- 如果數(shù)據(jù)為null則不讓這個數(shù)據(jù)參加sql語句的執(zhí)行
- 插入多條數(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
榄审。
可以通過這兩個標簽來解決上面提到的比大小問題:
- 創(chuàng)建Mapper方法為
List<Product> selectProductByPrice(String op,double value)
砌们,其中,op為符號搁进,>為匹配大于value的浪感,<為匹配小于value的,>=為匹配大于等于value的饼问,<=為匹配小于等于value的影兽,=為匹配等于value的。 - 修改Mapper映射文件匆瓜,在文件中添加下面內容:
<select id="selectProductByPrice" resultType="product"> select * from Product <where> <if test='op==">".toString()'> price > #{value} </if> <if test='op=="<".toString()'> price < #{value} </if> <if test='op==">=".toString()'> price >= #{value} </if> <if test='op=="<=".toString()'> price <= #{value} </if> <if test="op=='='.toString()"> price = #{value} </if> </where> </select>
- 編寫一個測試類來測試這個方法(略)
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,'李四';