瑞安做網(wǎng)站建設(shè)湖南網(wǎng)站建設(shè)seo
動態(tài) SQL 是 MyBatis 的強(qiáng)大特性之一。如果你使用過 JDBC 或其它類似的框架,你應(yīng)該能理解根據(jù)不同條件拼接 SQL 語句有多痛苦,例如拼接時要確保不能忘記添加必要的空格,還要注意去掉列表最后一個列名的逗號。利用動態(tài) SQL,可以徹底擺脫這種痛苦。
if
choose (when, otherwise)
trim (where, set)
foreach
1 if
使用動態(tài) SQL 最常見情景是根據(jù)條件包含 where 子句的一部分。比如:
<select id="findActiveBlogWithTitleLike" resultType="Blog">SELECT * FROM BLOGWHERE state = ‘ACTIVE’<if test="title != null">AND title like #{title}</if>
</select>
這條語句提供了可選的查找文本功能。如果不傳入 “title”,那么所有處于 “ACTIVE” 狀態(tài)的 BLOG 都會返回;如果傳入了 “title” 參數(shù),那么就會對 “title” 一列進(jìn)行模糊查找并返回對應(yīng)的 BLOG 結(jié)果(細(xì)心的讀者可能會發(fā)現(xiàn),“title” 的參數(shù)值需要包含查找掩碼或通配符字符)。
如果希望通過 “title” 和 “author” 兩個參數(shù)進(jìn)行可選搜索該怎么辦呢?首先,我想先將語句名稱修改成更名副其實(shí)的名稱;接下來,只需要加入另一個條件即可。
<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>
2 choose、when、otherwise
有時候,我們不想使用所有的條件,而只是想從多個條件中選擇一個使用。針對這種情況,MyBatis 提供了 choose 元素,它有點(diǎn)像 Java 中的 switch 語句。
還是上面的例子,但是策略變?yōu)?#xff1a;傳入了 “title” 就按 “title” 查找,傳入了 “author” 就按 “author” 查找的情形。若兩者都沒有傳入,就返回標(biāo)記為 featured 的 BLOG(這可能是管理員認(rèn)為,與其返回大量的無意義隨機(jī) 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>
3 trim、where、set
前面幾個例子已經(jīng)方便地解決了一個臭名昭著的動態(tài) SQL 問題?,F(xiàn)在回到之前的 “if” 示例,這次我們將 “state = ‘ACTIVE’” 設(shè)置成動態(tài)條件,看看會發(fā)生什么。
<select id="findActiveBlogLike" resultType="Blog">SELECT * FROM BLOGWHERE<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
這會導(dǎo)致查詢失敗。如果匹配的只是第二個條件又會怎樣?這條 SQL 會是這樣:
SELECT * FROM BLOG
WHERE
AND title like ‘someTitle’
這個查詢也會失敗。這個問題不能簡單地用條件元素來解決。這個問題是如此的難以解決,以至于解決過的人不會再想碰到這種問題。
MyBatis 有一個簡單且適合大多數(shù)場景的解決辦法。而在其他場景中,可以對其進(jìn)行自定義以符合需求。而這,只需要一處簡單的改動:
<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 元素只會在子元素返回任何內(nèi)容的情況下才插入 “WHERE” 子句。而且,若子句的開頭為 “AND” 或 “OR”,where 元素也會將它們?nèi)コ?/p>
如果 where 元素與你期望的不太一樣,你也可以通過自定義 trim 元素來定制 where 元素的功能。比如,和 where 元素等價的自定義 trim 元素為:
<update id="updateBatch" parameterType="java.util.List"><!--@mbg.generated-->update bs_factory_calendar<trim prefix="set" suffixOverrides=","><trim prefix="SET_TIME = case" suffix="end,"><foreach collection="list" index="index" item="item">when FACTORY_CALENDAR_ID = #{item.factoryCalendarId,jdbcType=VARCHAR} then #{item.setTime,jdbcType=VARCHAR}</foreach></trim><trim prefix="WEEK = case" suffix="end,"><foreach collection="list" index="index" item="item">when FACTORY_CALENDAR_ID = #{item.factoryCalendarId,jdbcType=VARCHAR} then #{item.week,jdbcType=VARCHAR}</foreach></trim></trim>where FACTORY_CALENDAR_ID in<foreach close=")" collection="list" item="item" open="(" separator=", ">#{item.factoryCalendarId,jdbcType=VARCHAR}</foreach></update>
<insert id="insertOrUpdateSelective" parameterType="com.inspur.spring.pojo.BsFactoryCalendar"><!--@mbg.generated-->insert into bs_factory_calendar<trim prefix="(" suffix=")" suffixOverrides=","><if test="factoryCalendarId != null">FACTORY_CALENDAR_ID,</if><if test="setTime != null">SET_TIME,</if></trim>values<trim prefix="(" suffix=")" suffixOverrides=","><if test="factoryCalendarId != null">#{factoryCalendarId,jdbcType=VARCHAR},</if><if test="setTime != null">#{setTime,jdbcType=VARCHAR},</if></trim>on duplicate key update<trim suffixOverrides=","><if test="factoryCalendarId != null">FACTORY_CALENDAR_ID = #{factoryCalendarId,jdbcType=VARCHAR},</if><if test="setTime != null">SET_TIME = #{setTime,jdbcType=VARCHAR},</if></trim></insert>
<update id="updateByPrimaryKeySelective" parameterType="com.inspur.spring.pojo.BsFactoryCalendar"><!--@mbg.generated-->update bs_factory_calendar<set><if test="updateTime != null">UPDATE_TIME = #{updateTime,jdbcType=TIMESTAMP},</if><if test="comId != null">COM_ID = #{comId,jdbcType=VARCHAR},</if></set>where FACTORY_CALENDAR_ID = #{factoryCalendarId,jdbcType=VARCHAR}</update>
4 foreach
<select id="selectPostIn" resultType="domain.blog.Post">SELECT *FROM POST P<where><foreach item="item" index="index" collection="list"open="ID in (" separator="," close=")" nullable="true">#{item}</foreach></where>
</select>