MyBatis(五)動態SQL 之 if 與 where 標簽


一、SQL 多條件來查詢

  1、在 EmployeeMapper 接口中聲明方法

//根據id, lastNname, age, sex多條件查詢員工信息
public List<Emp> getEmpListByMoreCondition(Emp  emp);

 

  2、在 EmployeeMapper.xml 中配置 SQL 語句

     <!-- public List<Emp> getEmpListByMoreCondition(Emp emp); 多條件查詢:若頁面中沒有設置此條件,SQL語句中一定不能有該條件 -->
     <select id="getEmpListByMoreCondition1" resultType="Emp"> select eid,ename,age,sex,did from emp where id = #{id} and last_name = #{lastName} and age = #{age} and sex = #{sex} </select>

    在這里可以看到,使用的是 SQL 拼接的方式,來進行多條件查詢的。

 

二、使用 if 標簽實現多條件查詢

  1、在 EmployeeMapperDynamicSQL 接口中聲明方法

public List<Employee> getEmpsByConditionIf(Employee employee);

 

  2、在 EmployeeMapperDynamicSQL.xml 中進行配置

    <!-- 1、查詢員工:要求攜帶了哪個字段查詢條件就帶上這個字段的值 public List<Employee> getEmpsByConditionIf(Employee employee); -->
    <!-- test:判斷表達式(OGNL)表達式 OGNL 表達式參照官方文檔或PPT c:if test 從參數中取值進行判斷 遇見特殊符號應該去寫轉義字符: " : &quot; & : &amp; OGNL 會進行字符串和與數字的轉換判斷 -->
    <select id="getEmpsByConditionIf" resultType="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()!=&quot;&quot;"> and email = #{email} </if>
            <if test="gender==0 or gender==1"> and gender = #{gender} </if>
    </select>

 

    <if> 標簽的作用:通過 test 表達式,用於拼接 SQL,如果 test 為 true,將其中的 SQL 進行拼接,否則不進行拼接。

    

  3、細節問題1

    當我們把 gender 字段改為"男、女"的字符格式時,然后重新修改 xml 中的配置:

  <select id="getEmpsByConditionIf" resultType="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()!=&quot;&quot;"> and email = #{email} </if>
            <if test="gender == '男' or gender == '女'"> and gender = #{gender} </if>
        </where>
    </select>

 

    測試信息:

 @Test public void testIf() throws IOException { //1、獲取 sqlSessionFactory
          SqlSessionFactory sqlSessionFactory = getsqlSessionFactory(); //2、獲取 sqlSession 實例,能直接執行已經映射的 SQL 語句
          SqlSession sqlSession = sqlSessionFactory.openSession(); try { EmployeeMapperDynamicSQL mapper = sqlSession.getMapper(EmployeeMapperDynamicSQL.class); //select * from tbl_employee where id=? and last_name like ? and email = ?
               Employee employee = new Employee(null, "%o%", "男","tom@126.com"); List<Employee> emps = mapper.getEmpsByConditionIf(employee); emps.forEach(System.out::println); } finally { sqlSession.close(); }

 

    運行結果:

 

   我們發現,這時並不能正常執行。

  重新修改配置文件:

  <select id="getEmpsByConditionIf" resultType="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()!=&quot;&quot;"> and email = #{email} </if>
            <if test='gender == "男" or gender == "女"'> and gender = #{gender} </if>
        </where>
    </select>

 

     修改了映射文件,重新運行。

     運行成功。

    小結

    (1)if 標簽中判斷字符串變量是否是字符串的時候,發現並不管用;

    (2)如果把變量的值用雙引號引起來,外面使用 單引號,這時就成功了;

    (3)只能解釋為 MyBatis 會把 '男' 解析為字符,而需要的是字符串,java 是強類型語言,字符串和字符不能直接比較,所以需要使用雙引號。

  4、細節問題2

    對於上面的拼接條件,如果使用了多條件拼接查詢,當有多個匹配條件時,可以使用 and 來連接。

    但是如果第一個條件如果不進行拼接,就會出現 where 后面多出一個 and 的情況。

    例如上面的情況,如果 id 為 null,就不會進行拼接該 SQL 片段,而是直接拼接第二個條件,這時就會出現一個 and 字段

select * from tbl_employee where and last_name = ? and email = ? and gender = ?

      這時 SQL 的執行就會出現問題。

 

  5、解決方案一

    在 where 后面添加一個恆成立的情況,如果第一個條件不匹配,也不會不執行。

    <select id="getEmpsByConditionIf" resultType="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()!=&quot;&quot;"> and email = #{email} </if>
            <if test="gender==0 or gender==1"> and gender = #{gender} </if>
    </select>

 

    執行的 SQL 語句:

select * from tbl_employee where 1=1 and last_name = ? and email = ? and gender = ?

     常用的恆等式有:

2>1
1=1
true

  

  6、解決方案二

    使用下面的 where 標簽

 

三、使用 where 條件

  使用 where 標簽優化多查詢查詢(方案二)
  <where> 標簽的作用:添加where關鍵字,同時去掉多余的and
  修改上面 xml 中的配置
    <select id="getEmpsByConditionIf" resultType="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()!=&quot;&quot;"> and email = #{email} </if>
            <if test="gender==0 or gender==1"> and gender = #{gender} </if>
        </where>
    </select>

 

  這時如果 id 還是 null,而不用再在 where 后面加恆等式,也可以執行成功。where 標簽會把多余的 and 去掉。
  執行的 SQL 語句:
select * from tbl_employee WHERE last_name like ? and email = ?

  

  注意

  (1)if 標簽和 where 標簽不一定必須同時使用,按實際需要進行使用;

  (2)if 標簽用於完成簡單的判斷;

  (3)where 用於解決 SQL 語句中 where 關鍵字以及條件中第一個 and 或者 or 的問題;

  (4)mybatis就會將where標簽中拼裝的sql,多出來的and或者or去掉,where只會去掉第一個多出來的and或者or。

 

四、總結

  查詢的時候如果某些字段沒帶可能 SQL 拼裝會有問題。

  (1)給 where 后面加上1=1,以后的條件都是 and xxx;

  (2)mybatis 使用where標簽來將所有的查詢條件包括在內,mybatis 就會將where標簽中拼裝的SQL,多出來的and或者or去掉;

  (3)where 只會去掉第一個多出來的and或者or;

 


免責聲明!

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



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