SSM-動態SQL


SSM-動態SQL

動態SQL主要是解決同一類SQL語句匹配不同的問題,舉個栗子:

加入我要執行一個查詢語句,但是是一個不確定的查詢語句,可能會根據ID去查,如果ID沒有就可能根據名字去查,或者說同時根據兩個去查。那么這時候SQL語句就是不確定的,就要用到mybatis動態SQL語句了,同時Mybatis是基於OGNL表達式的。

動態SQL語句

  • if
  • where
  • choose
    • when
    • otherwise
  • set
  • trim
  • foreach
  • sql
  • include
  • bind

數據形式

id the_name flower
1 小明 小紅花

if

if很簡單的知道,就是判斷條件的。
xml映射文件配置文件

<!--動態SQL if語句-->
<select id="query1" resultType="com.weno.pojo.Girl">
    select * from Girl where
    <if test= "the_name != null">
        the_name = #{the_name}
    </if>
    <if test= "flower != null">
        and flower = #{flower};
    </if>
</select>
@Test
public void m006() {
    SqlSession sqlSession = MybatisUtil.getSession();

    GirlMapper mapper = sqlSession.getMapper(GirlMapper.class);

    Girl g= new Girl();

    g.setName("小明");
    // g.setFlower("小紅花");
    Girl girl=mapper.query1(g);

    sqlSession.commit();
    sqlSession.close();
    System.out.printf(girl.toString());
}

如果此時我們將小紅花注釋掉查看一下運行結果:

DEBUG [main] - ==>  Preparing: select * from Girl where the_name = ? 
DEBUG [main] - ==> Parameters: 小明(String)
TRACE [main] - <==    Columns: id, the_name, flower
TRACE [main] - <==        Row: 1, 小明, 小紅花
DEBUG [main] - <==      Total: 1

在SQL語句中並沒有加上flower語句。但是此時卻有一個問題,如果the_namenull,而flower不為null,那么在SQL語句中豈不是多了一個and,變成了:

DEBUG [main] - ==>  Preparing: select * from Girl where and flower = ?; 

這時候程序肯定報錯,那么我們該如何處理呢?那么接下來說一下where標簽。

where

任然使用上面的例子:

<select id="query2" resultType="com.weno.pojo.Girl">
    select * from Girl
    <where>
        <if test="the_name != null">
            and the_name = #{the_name}
        </if>
        <if test="flower != null">
            and flower = #{flower}
        </if>
    </where>
</select>

這個跟上面的區別就是將where改成了<where>標簽。
<where>在這里的作用就是當標簽中有返回值時,就插入一個where,同時,如果標簽是以ANDOR【不區分大小寫】開頭時,就剔除。

choose

choose語句有點類似Java中的switch,當有一個符合時,就選擇那一個並跳出。
映射文件

<select id="query3" resultType="com.weno.pojo.Girl">
    select * from Girl where
    <choose>
        <when test="id != null and id!=''">
            id = #{id}
        </when>
        <when test="the_name != null and the_name != ''">
            the_name = #{the_name}
        </when>

        <otherwise>
            flower = #{flower}
        </otherwise>
    </choose>
</select>

在這種情況下,如果id符合的話,就不會再考慮下面的了。

@Test
public void m008() {
    SqlSession sqlSession = MybatisUtil.getSession();
    GirlMapper mapper = sqlSession.getMapper(GirlMapper.class);
    Girl g= new Girl();
    g.setId(1);
    g.setName("小明");
    g.setFlower("小紅花");
    Girl girl=mapper.query3(g);
    sqlSession.commit();
    sqlSession.close();
    System.out.printf(girl.toString());
}

SQL語句,在其中並沒有選擇the_name

DEBUG [main] - ==>  Preparing: select * from Girl where id = ? 

set

set是一個更新數據的標簽

<update id="update1">
    update Girl set the_name=#{the_name},flower=#{flower} where id=#{id};
</update>

java代碼:

@Test
public void m009() {
    SqlSession sqlSession = MybatisUtil.getSession();
    GirlMapper mapper = sqlSession.getMapper(GirlMapper.class);
    Girl g= new Girl();
    g.setId(1);
    g.setName("小紅");
// g.setFlower("小明花");
    mapper.update1(g);
    sqlSession.commit();
    sqlSession.close();
}

如果此時這樣執行,那么在數據庫表里面,flower的數據即為null。假如此時,使用if標簽

<update id="update2">
    update Girl set
    <if test="the_name != null and the_name != ''">
    the_name=#{the_name},
    </if>
    <if test="flower != null and flower != ''">
        flower=#{flower}
    </if>
    where id=#{id};
</update>

那么此時會出現一個問題,如果第一個符合,而第二個不符合,那么就會多一個,,此時使用<set>標簽就可以解決這個問題

<update id="update3">
    update Girl
    <set>
        <if test="the_name != null and the_name != ''">
            the_name=#{the_name},
        </if>
        <if test="flower != null and flower != ''">
            flower=#{flower},
        </if>
    </set>
    where id=#{id};
</update>

<set>標簽和<where>有點類似,在<set>標簽中,如果結尾有逗號,就將逗號去除。

trim

<trim>就很神奇了,它既可以實現<set>的功能,也能夠實現<where>的功能。

trim可以在前面增加和刪除內容,也可在在后面也執行此操作。

<update id="query0">
    <trim prefixOverrides="and | or">
        <if test="the_name != null">
            and the_name = #{the_name}
        </if>
        <if test="flower != null">
            and flower = #{flower}
        </if>
    </trim>
</update>

去除第一個and或則是or

  • prefix:前綴      
  • prefixoverride:去掉第一個a
  • suffix:后綴  
  • suffixoverride:去掉最后一個

foreach

foreach 類似for循環。

改寫我們用 foreach 來改寫 select * from Girl where id in (1,2,3)

映射文件

    <!-- collection:指定輸入對象中的集合屬性,使用@Param("ids")指令名字 item:每次遍歷生成的對象 open:開始遍歷時的拼接字符串 close:結束時拼接的字符串 separator:遍歷對象之間需要拼接的字符串 select * from Girl where id in (1,2,3) -->
<select id="queryByIDs" resultType="com.weno.pojo.Girl">
    select * from Girl where
    <foreach collection="ids" item="id" open="id in (" close=" ) " separator=",">
            #{id}
    </foreach>
</select>

sql

SQL片段主要是為了提高效率,可以講動態SQL的判斷部分獨立處理,提高程序的復用率。

<!-- id是sql片段的標識,一定要唯一 -->
<sql id="sql_1"> 
  <if test="the_name != null and the_name != ''">
      the_name = #{the_name}
  </if>
</sql>

注意:在SQL片段中,不要包括where

include

引用SQL片段,使用上面的例子

<select id="query2" resultType="com.weno.pojo.Girl">
    select * from Girl
    <where>
        <include refid="sql_1"/>
        <if test="flower != null">
            and flower = #{flower}
        </if>
    </where>

就是如此簡單。

bind

<bind>簡單的來說,就是使值變成另外一個。

例如在模糊查詢語句中要使傳入的值變成%*%,那么就使用bind進行連接。

<select id="queryLikeByName" resultType="com.weno.pojo.Girl">
    select * from Girl
    <bind name="_name" value="'%'+the_name+'%'"/>
    <!-- 如果the_name代表A,那么_name則代表%A% -->
    where the_name like #{_name}
</select>

mybati的動態語句大概就這樣了,如果學會了使用,那么毋庸置疑,可以大量的提高我們的效率。
不過更多的mybatis的使用,可以參考mybatis的 官方文檔

媽耶,第一次寫這么多的字,紀念一下!!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM