1. 程式人生 > >程式筆記:MyBatis 動態SQL和模糊查詢

程式筆記: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 表示式建立一個變數井將其繫結到上下文中。