1. 程式人生 > >動態SQL之、條件判斷

動態SQL之、條件判斷

錯誤方式一: 
在mybatis的動態sql語句中使用<if>標籤可以判斷sql中的條件是否成立。

    <select id="getPerson" resultType="com.lzj.bean.Employee">
        select * from tbl_employee
        where
            <if test="id!=null">
                id=#{id}
            </if>
            <if test="lastName!=null and lastName!=''"
> and last_name like #{lastName} </if> <if test="email!=null and email.trim()!=''"> and email=#{email} </if> <if test="gender==0 or gender==1"> and gender=#{gender} </if
> </select>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

在上面的動態sql語句中存在一個問題,當第一條sql判斷語句

            <if test="id!=null">
                id=#{id}
            </if>
  • 1
  • 2
  • 3

失敗時,即id值為null,而lastName、email和gender判斷成功後,最後sql語句就會變為: 
select * from tbl_employee where and last_name like #{lastName} and email=#{email} and gender=#{gender}

 
where後面多一個and,執行sql時會失敗。

改正方式一: 
在where條件後面加了一條判斷1=1,然後在id的判斷後加上and關鍵字,這樣當下面if條件中的任何一個判斷失敗後,都不會影響整個sql語句。

    <select id="getPerson" resultType="com.lzj.bean.Employee">
        select * from tbl_employee
        where 1=1
            <if test="id!=null">
                and id=#{id}
            </if>
            <if test="lastName!=null and lastName!=''">
                and last_name like #{lastName}
            </if>
            <if test="email!=null and email.trim()!=''">
                and email=#{email}
            </if> 
            <if test="gender==0 or gender==1">
                and gender=#{gender}
            </if>
     </select>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

錯誤方式二: 
有些人習慣在每個if判斷中的資料庫欄位的後面加and關鍵字,例如

    <select id="getPerson" resultType="com.lzj.bean.Employee">
        select * from tbl_employee
        where
            <if test="id!=null">
                id=#{id} and
            </if>
            <if test="lastName!=null and lastName!=''">
                last_name like #{lastName} and
            </if>
            <if test="email!=null and email.trim()!=''">
                email=#{email} and
            </if> 
            <if test="gender==0 or gender==1">
                gender=#{gender}
            </if>
     </select>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

但是上述情況存在一個弊端,當最後一個if判斷gender失敗時,sql語句就變成了: 
select * from tbl_employee where id=#{id} and last_name like #{lastName} and email=#{email} and 
where條件的最後多一個and,sql語句執行的時候也會失敗。 
改正方式二: 
在最後一個if語句中庫表字段後加and關鍵字,然後在最後加1=1判斷

    <select id="getPerson" resultType="com.lzj.bean.Employee">
        select * from tbl_employee
        where
            <if test="id!=null">
                id=#{id} and
            </if>
            <if test="lastName!=null and lastName!=''">
                last_name like #{lastName} and
            </if>
            <if test="email!=null and email.trim()!=''">
                email=#{email} and
            </if> 
            <if test="gender==0 or gender==1">
                gender=#{gender} and
            </if>
            1=1
     </select>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

建議方式:

<where><if> 進行組合,當條件不成立時,if條件後的內容包括and也不會存在,因此不會對整個sql語句產生影響。注意and關鍵字要放在每個<if>語句中的庫表字段賦值的前面。因為,一旦判斷不成功,<where> 會把對應的and關鍵字去掉(還有or關鍵字)。

<select id="getPerson" resultType="com.lzj.bean.Employee">
    select * from tbl_employee
    <where>
        <!-- test:判斷表示式(OGNL)
        遇見特殊符號應該去寫轉義字元:&&、''等字元
        -->
        <if test="id!=null">
            id=#{id}
        </if>
        <if test="lastName!=null and lastName!=''">
            and last_name like #{lastName}
        </if>
        <if test="email!=null and email.trim()!=''">
            and email=#{email}
        </if> 
        <!-- ognl會進行字串與數字的轉換判斷  "0"==0 -->
        <if test="gender==0 or gender==1">
            and gender=#{gender}
        </if>
    </where>
 </select>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
上述很多特殊字元可以寫成轉義的形式,例如
  • 1
 <select id="getEmpsByConditionIf" resultType="com.atguigu.mybatis.bean.Employee">
    select * from tbl_employee
    <!-- where -->
    <where>
        <if test="id!=null">
            id=#{id}
        </if>
        <if test="lastName!=null &amp;&amp; lastName!=&quot;&quot;">
            and last_name like #{lastName}
        </if>
        <if test="email!=null and email.trim()!=&quot;&quot;">
            and email=#{email}
        </if> 
        <if test="gender==0 or gender==1">
            and gender=#{gender}
        </if>
    </where>
 </select>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
注意,`<if>`失敗後, `<where>` 關鍵字只會去掉庫表字段賦值前面的and,不會去掉後面的and關鍵字,即注意,`<where>` 只會去掉`<if>` 語句中的最開始的and關鍵字。所以下面的形式是不可取的
  • 1
  • 2
<select id="getPerson" resultType="com.lzj.bean.Employee">
    select * from tbl_employee
    <where>
        <if test="id!=null">
            id=#{id} and
        </if>
        <if test="lastName!=null and lastName!=''">
            last_name like #{lastName} and
        </if>
        <if test="email!=null and email.trim()!=''">
            email=#{email} and
        </if> 
        <if test="gender==0 or gender==1">
            gender=#{gender}
        </if>
    </where>
 </select>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

`` 
因為,
失敗後,`不會自動去掉後面的and關鍵字,這種形式與錯誤方式二種原理相同。