程式筆記:MyBatis 動態SQL和模糊查詢
之前用mybatis在xml中寫sql語句用到過<if>
標籤,但是不知道這是動態SQL(尷尬),最近空閒整理一下常用的動態SQL。好記性不如爛筆頭
以圖 t_user 表為例:
1. if 語句
根據 userNo 和 name 來查詢資料。如果userNo為空,那麼將只根據name來查詢;反之只根據userNo來查詢.
<select id="getUserByUsernoAndName" returnMap="BaseResultMap" parameterType="com.xxb.domain.UserPO">
<!-- 這裡和普通的sql 查詢語句差不多,對於只有一個引數,後面的 #{id}表示佔位符,裡面不一定要寫id,
寫啥都可以,但是不要空著,如果有多個引數則必須寫pojo類裡面的屬性 -->
select * from t_user where userNo=#{userNo} and name=#{name}
</select>
上面的查詢語句,我們可以發現,如果 #{userNo} 為空,那麼查詢結果也是空,如何解決這個問題呢?使用 if 來判斷
<select id="getUserByUsernoAndName" returnMap="BaseResultMap" parameterType="com.xxb.domain.UserPO">
select * from t_user where 1=1
<if test="userNo != null">
and userNo=#{userNo}
</if>
<if test="name != null">
and name=#{name}
</if>
</select>
但是加一個 1=1
作為條件是不是很奇怪,用where 語句來解決這個問題
2. if+where 語句
<select id="getUserByUsernoAndName" returnMap="BaseResultMap" parameterType="com.xxb.domain.UserPO">
select * from t_user
<where>
<if test="userNo != null">
and userNo=#{userNo}
</if>
<if test="name != null">
and name=#{name}
</if>
</where>
</select>
這個“where”標籤會知道如果它包含的標籤中有返回值的話,它就插入一個‘where’。此外,如果標籤返回的內容是以AND 或OR 開頭的,則它會剔除掉。
3. if+set 語句
<update id="updateUserById" parameterType="com.xxb.domain.UserPO">
update t_user u
<set>
<if test="userNo != null">
u.userNo=#{userNo},
</if>
<if test="name != null">
u.name=#{name}
</if>
</set>
where id=#{id}
</update>
4. choose(when,otherwise) 語句
有時候,我們不想用到所有的查詢條件,只想選擇其中的一個,查詢條件有一個滿足即可,使用 choose 標籤可以解決此類問題,類似於 Java 的 switch 語句
<select id="getUserByChoose" returnMap="BaseResultMap" parameterType="com.xxb.domain.UserPO">
select * from t_user
<where>
<choose>
<when test="id != null">
and id=#{id}
</when>
<when test="userNo != null">
and userNo=#{userNo}
</when>
<otherwise>
and name=#{name}
</otherwise>
</choose>
</where>
</select>
這裡我們有三個條件,id,userNo,name,只能選擇一個作為查詢條件
如果 id 不為空,那麼查詢語句為:select * from t_user where id=?
如果 id 為空,那麼看userNo 是否為空,如果不為空,那麼語句為 select * from _user where userNo=?;
如果 userNo 為空,那麼查詢語句為 select * from t_user where name=?
5. foreach 語句
我們需要查詢 t_user 表中 id 分別為1,2,3的使用者
sql語句:select * from t_user where id=1 or id=2 or id=3
select * from t_user where id in (1,2,3)
<select id="selectUserByListId" returnMap="BaseResultMap" parameterType="java.util.List">
select * from t_user
<where>
<!-- collection:指定輸入物件中的集合屬性
item:每次遍歷生成的物件
open:開始遍歷時的拼接字串
close:結束時拼接的字串
separator:遍歷物件之間需要拼接的字串
select * from t_user where 1=1 and (id=1 or id=2 or id=3)
-->
<foreach collection="ids" item="id" open="and (" close=")" separator="or">
id=#{id}
</foreach>
</where>
</select>
6. trim 語句
trim標記是一個格式化的標記,可以完成set或者是where標記的功能
用 trim 改寫上面第二點的 if+where 語句
<select id="getUserByUsernoAndName" returnMap="BaseResultMap" parameterType="com.xxb.domain.UserPO">
select * from t_user
<!--
<where>
<if test="userNo != null">
and userNo=#{userNo}
</if>
<if test="name != null">
and name=#{name}
</if>
</where>
-->
<trim prefix="where" prefixOverrides="and | or">
<if test="userNo != null">
and userNo=#{userNo}
</if>
<if test="name != null">
and name=#{name}
</if>
</trim>
</select>
prefix:字首
prefixoverride:去掉第一個and或者是or
suffixoverride:去掉最後一個標記(就像是上面字首中的and or一樣)
7. SQL 片段
有時候可能某個 sql 語句我們用的特別多,為了增加程式碼的重用性,簡化程式碼,我們需要將這些程式碼抽取出來,然後使用時直接呼叫。
比如:我們表中有blob型別欄位,平時查詢結果用不到這個欄位,那麼我們就把這個程式碼抽取出來,如下:
<sql id="Blob_Column_List">
base64
</sql>
<sql id="Base_Column_list">
id,name,preview,styleId,laytype,width,height
</sql>
<select id="getByStyleId" parameterType="java.lang.Integer" resultMap="BaseResultMap">
select <include refid="Base_Column_list"/> from t_style_inner where styleId=#{styleId} order by laytype asc
</select>
動態 sql 語句的編寫往往是一個拼接的問題,要注意編寫規範。
8. SQL 模糊查詢
現在有個這樣的場景,同一個輸入框即可以輸入id也可以輸入name,返回的結果是兩者的疊加,比如說輸入框值為‘1’,返回結果包含id為‘1’、name中包含‘1’的結果集。
<select id="search" resultType="com.×××.×××.db.RoomPo">
<if test="roomPo.name != null">
<bind name="likeName" value="'%'+ roomPo.name +'%'"/>
</if>
<if test="roomPo.id != null">
<bind name="likeId" value="roomPo.id"/>
</if>
select * from t_room where status=1
<if test="roomPo.name != null">
<choose>
<when test="roomPo.id != null">
and ( id = #{likeId} or
</when>
<otherwise>
and (
</otherwise>
</choose>
name like #{likeName})
</if>
limit #{begin},#{pageSize}
</select>
bind 標籤可以使用 OGNL 表示式建立一個變數井將其繫結到上下文中。