MyBatis知識六 動態SQL語句

MyBatis動態SQL語句的關鍵字有:
if
choose (when, otherwise)
trim (where, set)
foreach
等類型。

MyBatis 採用功能強大的基於 OGNL 的表達式來消除其他元素。
拼接sql語句的好處在於,可以進行選擇性查詢,如果不傳遞參數則是進行全部查詢,如果有參數傳遞則是進行拼接到對應的sql上。
where 元素知道只有在一個以上的if條件有值的情況下才去插入“WHERE”子句。而且,若最後的內容是“AND”或“OR”開頭的,where 元素也知道如何將他們去除。

IF

IF語句的使用通常是有條件的 進行SQL語句的Where條件的查詢。所以注意【Where】標籤的使用。

<select id="findUserList" parameterType="com.wf.model.UserVo" resultType="com.wf.model.UserExtends">
        select * from user
        <where>
        <if test="userExtends!=null">
            <if test="userExtends.sex!=null and userExtends.sex!=''">
                and user.sex=#{userExtends.sex}
            </if>
            <if test="userExtends.username!=null and userExtends.username!='' ">
                and user.username like '%${userExtends.username}%'
            </if>
        </if>
        </where>
    </select>

說明: 上述的SQL語句就是利用IF條件進行SQL語句的拼裝,這裏,利用IF標籤的test屬性進行條件的判斷,如果條件成立,則進行SQL語句拼裝,如果不成立則跳過此條件語句的拼裝。
解釋:當我們傳入的條件UserVo爲NULL時,則直接進行的語句爲“select * from user”;
如果我們UserVo不爲空時,然後我們又會分別判斷我們的sex和username是不是爲空或者null,如果都有值則會都進行拼接,此時的SQL語句爲:“select * from user where user.sex = ‘參數一’ and user.username like ‘%參數二%’ ”;

choose(when, otherwise)

choose的使用,主要是在多個條件下進行選擇匹配時使用,比如我們常說的在,兩個中選其中的一個條件,它有點像 Java 中的 switch 語句,只進行匹配條件成功的語句進行拼接。

<select id="findUserListChoose" parameterType="com.wf.model.UserVo" resultType="com.wf.model.UserExtends">
        select * from user 
        <where>
            <choose>
                <when test="userExtends.sex!=null and userExtends.sex!=''">
                    user.sex=#{userExtends.sex}
                </when>
                <when test="userExtends.username!=null and userExtends.username!=''">
                    and user.username like '%${userExtends.username}%' 
                </when>
                <otherwise>
                    and 1=1
                </otherwise>
            </choose>
        </where>
    </select>

說明:上述的SQL則是在進行條件匹配,如果when標籤的條件進行匹配成功,那麼就進行拼接SQL語句,如果所有的when條件都不成立的情況下,則是進行otherwise匹配。

trim (where, set)

自定義 trim 元素是用來定製我們想要的功能。
1、由於我們的where元素知道只有在一個以上的if條件有值的情況下才去插入“WHERE”子句。而且,若最後的內容是“AND”或“OR”開頭的,where 元素也知道如何將他們去除。
這樣的話,我們可以利用我們的trim元素進行等價轉化。

<!-- trim 語法  -->
    <trim prefix="WHERE" prefixOverrides="AND |OR ">
      ... 
    </trim>


<!-- trim 配置 -->
    <select id="findUserListtrim" parameterType="com.wf.model.UserVo" resultType="com.wf.model.UserExtends">
        select * from user
        <trim prefix="where" prefixOverrides="AND |OR |String">
        <if test="userExtends!=null">
            <if test="userExtends.sex!=null and userExtends.sex!=''">
                String user.sex=#{userExtends.sex}
            </if>
            <if test="userExtends.username!=null and userExtends.username!='' ">
                and user.username like '%${userExtends.username}%'
            </if>
        </if>
    </trim>
    </select>


// 測試用例打印的語句
Preparing: select * from user where user.sex=? and user.username like '%張三%' 

說明:prefixOverrides 屬性會忽略通過管道分隔的文本序列(注意此例中的空格也是必要的)。它帶來的結果就是所有在 prefixOverrides 屬性中指定的內容將被移除,並且插入 prefix 屬性中指定的內容。,此處是利用管道分隔符將我們的String字符進行替換成了 where字符。

set動態更新語句,set 元素可以被用於動態包含需要更新的列,而捨去其他的

<update id="updateAuthorIfNecessary">
  update Author
    <set>
      <if test="username != null">username=#{username},</if>
      <if test="password != null">password=#{password},</if>
      <if test="email != null">email=#{email},</if>
      <if test="bio != null">bio=#{bio}</if>
    </set>
  where id=#{id}
</update>

<!-- 等價的trim語句 -->

<trim prefix="SET" suffixOverrides=",">
  ...
</trim>

foreach

foreach 元素的功能是非常強大的,它允許你指定一個集合,聲明可以用在元素體內的集合項和索引變量。它也允許你指定開閉匹配的字符串以及在迭代中間放置分隔符。這個元素是很智能的,因此它不會偶然地附加多餘的分隔符。通常是在構建 IN 條件語句的時候
你可以將任何可迭代對象(如列表、集合等)和任何的字典或者數組對象傳遞給foreach作爲集合參數。當使用可迭代對象或者數組時,index是當前迭代的次數,item的值是本次迭代獲取的元素。當使用字典(或者Map.Entry對象的集合)時,index是鍵,item是值。

    collection :傳遞參數對象中的集合屬性名 
    item : 集合中存放的變量別名,用在下面的引用 
    open :開始遍歷時拼接的字符串
    close :結束遍歷時拼接的字符串
    separator 遍歷的兩個對象中需要拼接的字符串  
<select id="findUserList" parameterType="com.wf.model.UserVo" resultType="com.wf.model.UserExtends">
        select * from user
        <where>
        <include refid="usersql"></include>
        </where>
    </select>

<!--  sql語句片段引用   -->
<sql id="usersql">
        <if test="userExtends!=null">
            <if test="userExtends.sex!=null and userExtends.sex!=''">
                and user.sex=#{userExtends.sex}
            </if>
            <if test="userExtends.username!=null and userExtends.username!='' ">
                and user.username like '%${userExtends.username}%'
            </if>
        </if>
        <!--sql : select * from user where name like '%張三' and id IN(17,18,19) -->
        <if test="ids!=null"> 
            <foreach collection="ids" item="user_id" open="and id in(" close=")" separator=",">
            #{user_id}
        </foreach>
        </if>
</sql>

<!--  UserVo類  -->
public class UserVo {
    private UserExtends userExtends;

    private List<Integer> ids;   /// 設置接受多個參數的ids
}

// 測試方法 
@Test
    public void testfindUserList() {  //    測試foreach
        SqlSession session = sqlsessionfactory.openSession();
        UserDaoMapper userDaoMapper = session.getMapper(UserDaoMapper.class);
        UserVo uservo = new UserVo();
        UserExtends userExtends = new UserExtends();
        userExtends.setSex("男");
        //userExtends.setUsername("張三");
        uservo.setUserExtends(userExtends);
        List<Integer> list = new ArrayList<Integer>();  //  屬性設置
        list.add(17);
        list.add(18);
        list.add(19);
        uservo.setIds(list);
        List<UserExtends> userList = userDaoMapper.findUserList(uservo);
        for(UserExtends u :userList){
            System.out.println(u.getUsername());
        }
    }

// 測試用例 打印SQL語句
Preparing: select * from user WHERE user.sex=? and id in( ? , ? , ? ) 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章