如果使用JDBC或者其他框架,很多時候你得根據需要去拼接SQL,這是一個麻煩的事情,而MyBatis提供對SQL語句動態的組裝能力,而且它只有幾個基本的元素,非常簡單明了,大量的判斷都可以在MyBatis的映射XML文件里面配置,以達到許多我們需要大量代碼才能實現的功能,大大減少了我們編寫代碼的工作量,這體現了MyBatis的靈活性、高度可配置性和可維護性。MyBatis也可以在注解中配置SQL,但是由於注解中配置功能受限,對於復雜的SQL而言可讀性很差,所以使用較少。
關於MyBatis的注解使用可以參考我的這篇文章MyBatis實戰之初步
今天主要講解這么幾個常用的動態SQL:
1.if
2.choose、when、otherwise
3.trim、where、set
4.foreach
5.test
6.bind
一、if
if通常與where一起連用比較多
如下代碼所示:
<select id="selectName" parameterType="String" resultMap="BaseResultMap"> select <include refid="Base_Column_List"/> from `user` <where> <if test="userName!=''"> and user_name = #{userName} </if> </where> </select>
<if>中的test通常判斷的條件是不等於Null或者空字符串,除此之外還可以進行比較判斷比如大於等於小於等這樣的。
二、choose、when、otherwise
<select id="selectName" parameterType="String" resultMap="BaseResultMap"> select <include refid="Base_Column_List"/> from `user` <choose> <when test="userName!=null and userName!=''"> where userName = #{userName} </when> <otherwise> where sex = #{sex} </otherwise> </choose> </select>
你可以將<choose><when></when><otherwise></otherwise></choose>理解為Java中的if-else或者是if-else if-else
三、trim、where、set
trim+where示例:
<select id="selectName" parameterType="String" resultMap="BaseResultMap"> select <include refid="Base_Column_List"/> from `user` <trim prefix="where" prefixOverrides="AND |OR"> <if test="userName !=null and userName!=''"> and user_name = #{userName} </if> </trim> </select>
prefix:前綴
prefixoverride:去掉第一個and或者是or
trim+set示例:
update user <trim prefix="set" suffixoverride="," suffix=" where id = #{id} "> <if test="name != null and name.length()>0"> name=#{name} , </if> <if test="gender != null and gender.length()>0"> gender=#{gender} , </if> </trim>
prefix同trim+where的意思是一樣,都是前綴。
suffixoverride:去掉最后一個逗號(也可以是其他的標記,就像是上面前綴中的and一樣)
suffix:后綴
四、foreach
批量更新示例:
<update id="udpateUserLogoStatu" parameterType="java.util.List"> <foreach collection="users" item="user" index="index" separator=";"> update `user` <set> logo = 1 </set> where logo = #{user.logo} </foreach> </update>
可以參考這篇文章:mybatis的批量更新實例
foreach相關參數解釋:
collection配置的users是傳遞進來的參數名稱,它可以是一個數組或者List、Set等集合;
item配置的是循環中當前的元素;
index配置的是當前元素在集合的位置下標;
separator是各個元素的間隔符;
還有代碼中沒有展示的open和close,它們的含義是以什么符號將這些元素包裝起來。
在SQL中對於in語句我們常常使用,對於大量數據的in語句需要我們特別注意,因為它會消耗大量的性能,還有一些數據庫的SQL對執行的SQL長度也有限制。所以我們使用它的時候需要預估一下這個collection對象的長度。
五、test
至於test就不提太多了,在<where>+<if>中用到非常頻繁。
六、bind
bind通常用於綁定參數,然后引用,在實際開發中用的也不少。
bind的示例:
<select id="getUserList" resultType="com.blog.entity.User"> <!-- bind:可以將OGNL表達式的值綁定到一個變量中,方便后來引用這個變量的值 --> <bind name="userName" value="'%'+userName+'%'"/> eName是employee中一個屬性值 SELECT * FROM `user` <if test="userName!=null"> where ename like #{userName} </if> </select>
動態SQL一般常見的問題,就是查詢條件出錯,一般要么是參數問題,或者是多個字段and拼接出問題。
另外還有一點要提醒,在要用動態SQL之前,最好還是將SQL先執行一遍,確定沒有問題后,再改為動態SQL,最后再單元測試多個邊界條件測試下,確保沒有問題后,再編寫對應的邏輯Controller。