【Mybatis】MyBatis之動態SQL(六)
MyBatis 的強大特性之一便是它的動態 SQL,本章介紹動態 SQL
查看本章,請先閱讀【Mybatis】MyBatis對表執行CRUD操作(三)。
本例表結構
1 CREATE TABLE `employee` ( 2 `id` int(11) NOT NULL AUTO_INCREMENT, 3 `last_name` varchar(255) DEFAULT NULL, 4 `gender` char(1) DEFAULT NULL, 5 `email` varchar(255) DEFAULT NULL 6 PRIMARY KEY (`id`) 7) ENGINE=InnoDB DEFAULT CHARSET=utf8;
if
if標簽:用於邏輯判斷,其中test屬性,填寫的是判斷表達式(OGNL)
示例
1、EmployeeMapper新增Sql如下:
1 <!-- if:判斷 --> 2 <select id="testConditionIf" 3 resultType="com.hd.test.pojo.Employee"> 4 select id, last_name lastName, gender from employee 5 <!-- 6test:判斷表達式(OGNL) OGNL參照PPT或者官方文檔。 7 c:if test 從參數中取值進行判斷 遇見特殊符號應該去寫轉義字符: &&: 8 9 --> 10 where 1 = 1 11 <if test="id != null"> 12 AND id = #{id} 13 </if> 14 <!-- 表達式中,字符串使用‘‘單引號引起來 --> 15 <if test="lastName != null and lastName.trim() != ‘‘"> 16 AND last_name = #{lastName} 17 </if> 18 <!-- ognl會進行字符串與數字的轉換判斷 "0"==0 --> 19 <if test="gender==0 or gender==1"> 20 AND gender = #{gender} 21 </if> 22 <!-- 轉義字符: && == && "" == ""--> 23 <if test="email != null && lastName!="""> 24 AND email = #{email} 25 </if> 26 </select>
2、EmployeeMapper接口中,新增方法
1 public List<Employee> testConditionIf(Employee employee);
3、測試方法
1 @Test 2 public void test001() throws IOException { 3 4 InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml"); 5 SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream); 6 7 SqlSession session = sessionFactory.openSession(); 8 9 try { 10 EmployeeMapper mapper = session.getMapper(EmployeeMapper.class); 11 List<Employee> list = mapper.testConditionIf(new Employee(null, "0", null)); 12 System.out.println(list.size()); 13 for (Employee employee : list) { 14 System.out.println(list); 15 } 16 } catch (Exception e) { 17 e.printStackTrace(); 18 } finally { 19 session.close(); 20 } 21 }
4、執行結果
choose
有時我們不想應用到所有的條件語句,而只想從中擇其一項。針對這種情況,MyBatis 提供了 choose 元素,它有點像 Java 中的 switch 語句。
示例
1、EmployeeMapper新增Sql如下:
1 <!-- choose --> 2 <select id="testConditionChoose" resultType="com.hd.test.pojo.Employee"> 3 select id, last_name lastName, gender from employee 4 where 1 = 1 5 <choose> 6 <when test="id != null"> 7 AND id = #{id} 8 </when> 9 <when test="lastName != null"> 10 AND last_name = #{lastName} 11 </when> 12 <when test="gender != null"> 13 AND gender = #{gender} 14 </when> 15 <when test="email != null"> 16 AND email = #{email} 17 </when> 18 <otherwise> 19 AND 1 = 1 20 </otherwise> 21 </choose> 22 </select>
2、EmployeeMapper接口中,新增方法
1 public List<Employee> testConditionChoose(Employee employee);
3、測試方法
1 @Test 2 public void test002() throws IOException { 3 4 InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml"); 5 SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream); 6 7 SqlSession session = sessionFactory.openSession(); 8 9 try { 10 EmployeeMapper mapper = session.getMapper(EmployeeMapper.class); 11 List<Employee> list = mapper.testConditionChoose(new Employee(1, null, null, null)); 12 System.out.println(list.size()); 13 for (Employee employee : list) { 14 System.out.println(list); 15 } 16 } catch (Exception e) { 17 e.printStackTrace(); 18 } finally { 19 session.close(); 20 } 21 }
4、執行結果
where
where標簽:用於編寫帶where條件的sql,配合if標簽使用,它會自動去除首個AND前綴。
示例
1、EmployeeMapper新增Sql如下:
1 <!-- if + where --> 2 <select id="testConditionIfWhere" 3 resultType="com.hd.test.pojo.Employee"> 4 select id, last_name lastName, gender from employee 5 <where> 6 <if test="id != null"> 7 AND id = #{id} 8 </if> 9 <if test="lastName != null and lastName.trim() != ‘‘"> 10 AND last_name = #{lastName} 11 </if> 12 <if test="gender==0 or gender==1"> 13 AND gender = #{gender} 14 </if> 15 <if test="email != null && lastName!="""> 16 AND email = #{email} 17 </if> 18 </where> 19 </select>
2、EmployeeMapper接口中,新增方法
1 public List<Employee> testConditionIfWhere(Employee employee);
3、測試方法
1 @Test 2 public void test003() throws IOException { 3 4 InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml"); 5 SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream); 6 7 SqlSession session = sessionFactory.openSession(); 8 9 try { 10 EmployeeMapper mapper = session.getMapper(EmployeeMapper.class); 11 List<Employee> list = mapper.testConditionIfWhere(new Employee("小紅", "1", null)); 12 System.out.println(list.size()); 13 for (Employee employee : list) { 14 System.out.println(list); 15 } 16 } catch (Exception e) { 17 e.printStackTrace(); 18 } finally { 19 session.close(); 20 } 21 }
4、執行結果
trim
trim標簽:可以去掉字符串的首尾字符串,以及在字符串前後添加前後綴
示例
1、EmployeeMapper新增Sql如下:
1 <select id="testConditionIfTrim" resultType="com.hd.test.pojo.Employee"> 2 select id, last_name lastName, gender from employee 3 <!-- 後面多出的and或者or where標簽不能解決 4 prefix="":前綴:trim標簽體中是整個字符串拼串 後的結果。 prefix給拼串後的整個字符串加一個前綴 5 prefixOverrides="": 前綴覆蓋: 去掉整個字符串前面多余的字符 6 suffix="":後綴 suffix給拼串後的整個字符串加一個後綴 7 suffixOverrides="" 後綴覆蓋:去掉整個字符串後面多余的字符 --> 8 <trim prefix="where" prefixOverrides="AND"> 9 <if test="id != null"> 10 AND id = #{id} 11 </if> 12 <if test="lastName != null"> 13 AND last_name = #{lastName} 14 </if> 15 <if test="gender != null"> 16 AND gender = #{gender} 17 </if> 18 <if test="email != null"> 19 AND email = #{email} 20 </if> 21 </trim> 22 </select>
2、EmployeeMapper接口中,新增方法
1 public List<Employee> testConditionIfTrim(Employee employee);
3、測試方法
1 @Test 2 public void test004() throws IOException { 3 4 InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml"); 5 SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream); 6 7 SqlSession session = sessionFactory.openSession(); 8 9 try { 10 EmployeeMapper mapper = session.getMapper(EmployeeMapper.class); 11 List<Employee> list = mapper.testConditionIfTrim(new Employee(1, null, null, null)); 12 System.out.println(list.size()); 13 for (Employee employee : list) { 14 System.out.println(list); 15 } 16 } catch (Exception e) { 17 e.printStackTrace(); 18 } finally { 19 session.close(); 20 } 21 }
4、執行結果
foreach
動態 SQL 的另外一個常用的操作需求是對一個集合進行遍歷,通常是在構建 IN 條件語句的時候
示例
1、EmployeeMapper新增Sql如下:
1 <!-- foreach --> 2 <select id="testConditionForeach" resultType="com.hd.test.pojo.Employee"> 3 select id, last_name lastName, gender from employee 4 <!-- 5 collection:指定要遍歷的集合: 6 list類型的參數會特殊處理封裝在map中,map的key就叫list 7 item:將當前遍歷出的元素賦值給指定的變量 8 separator:每個元素之間的分隔符 9 open:遍歷出所有結果拼接一個開始的字符 10 close:遍歷出所有結果拼接一個結束的字符 11 index:索引。遍歷list的時候是index就是索引,item就是當前值 12 遍歷map的時候index表示的就是map的key,item就是map的值 13 14 #{變量名}就能取出變量的值也就是當前遍歷出的元素 15 --> 16 <foreach collection="ids" item="id" separator="," open="where id in (" close=")" > 17 #{id} 18 </foreach> 19 </select>
2、EmployeeMapper接口中,新增方法
1 public List<Employee> testConditionForeach(@Param("ids")List<Integer> ids);
3、測試方法
1 @Test 2 public void test005() throws IOException { 3 4 InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml"); 5 SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream); 6 7 SqlSession session = sessionFactory.openSession(); 8 9 try { 10 EmployeeMapper mapper = session.getMapper(EmployeeMapper.class); 11 List<Employee> list = mapper.testConditionForeach(Arrays.asList(1, 2, 3, 4)); 12 System.out.println(list.size()); 13 for (Employee employee : list) { 14 System.out.println(list); 15 } 16 } catch (Exception e) { 17 e.printStackTrace(); 18 } finally { 19 session.close(); 20 } 21 }
4、執行結果
set
set 元素會動態前置 SET 關鍵字,同時也會刪掉無關的逗號,因為用了條件語句之後很可能就會在生成的 SQL 語句的後面留下這些逗號
示例
1、EmployeeMapper新增Sql如下:
1 <!-- set --> 2 <update id="testConditionSet"> 3 update employee 4 <set> 5 <if test="lastName != null"> 6 last_name = #{lastName}, 7 </if> 8 <if test="gender != null"> 9 gender = #{gender}, 10 </if> 11 <if test="email != null"> 12 email = #{email}, 13 </if> 14 </set> 15 where id = #{id} 16 </update>
2、EmployeeMapper接口中,新增方法
1 public boolean testConditionSet(Employee employee);
3、測試方法
1 @Test 2 public void test006() throws IOException { 3 4 InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml"); 5 SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream); 6 7 SqlSession session = sessionFactory.openSession(); 8 9 try { 10 EmployeeMapper mapper = session.getMapper(EmployeeMapper.class); 11 boolean f = mapper.testConditionSet(new Employee(1, "小白", "1", null)); 12 System.out.println(f); 13 session.commit(); 14 } catch (Exception e) { 15 e.printStackTrace(); 16 } finally { 17 session.close(); 18 } 19 }
4、執行結果
bind
bind 元素可以從 OGNL 表達式中創建一個變量並將其綁定到上下文。比如:
1 <select id="testConditionBind" resultType="Blog"> 2 <bind name="pattern" value="‘%‘ + keyword + ‘%‘" /> 3 SELECT * FROM employee WHERE last_name LIKE #{pattern} 4 </select>
sql
可以用來包含其他sql
1 <sql id="selectSql">select id, last_name lastName, gender from employee</sql> 2 3 <select id="testConditionInclude" resultType="com.hd.test.pojo.Employee"> 4 <include refid="selectSql"></include> 5 where id = 1 6 </select>
Mybatis中2個內置參數 _parameter和_databaseId
【Mybatis】MyBatis之動態SQL(六)