一、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 從參數中取值進行判斷 遇見特殊符號應該去寫轉義字符: " : " & : & 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()!="""> 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()!="""> 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()!="""> 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()!="""> 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 條件
<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()!="""> and email = #{email} </if>
<if test="gender==0 or gender==1"> and gender = #{gender} </if>
</where>
</select>
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;