掌握MyBatis中動態SQL元素的使用
- if
- choose(when,otherwise)
- trim
- where
- set
- foreach
- <SQL>和<include>
在應用中我們經常會做一些動態的拼接條件,但是如果是JDBC我們可以用程序拼接SQL語句,如果MyBatis,我們可以使用動態SQL語句。例如按照員工姓名和工資來搜索員工信息,如果如果姓名和工資的檢索值為空,則忽略這個檢索條件。一般來說,我們都會用where 1=1類似這種寫法來實現,但是MyBatis就需要動態語句實現。
1 if元素
mapper.xml
1 <select id="selectStudentByCondition" parameterType="student" resultMap="BaseResultMap"> 2 select * from student where 1=1 3 <!-- 當傳入的屬性值為空或者空字符串時會忽略掉條件 4 注意:test中的pojo中的屬性名稱 5 like的使用 6 <![CDATA[ ]]>的使用--> 7 <if test="stuName !=null and stuName != ''"> 8 and stu_name like '%' ||#{stuName}||'%' 9 </if> 10 <if test="stuBirthdate != null"> 11 <![CDATA[and stu_birthdate>#{stuBirthdate}]]> 12 </if> 13 </select>
daoImpl.java
1 @Override 2 public void testQuery6(Student s){ 3 SqlSession session = fac.openSession(); 4 List<Student> result = session.selectList("student.selectStudentByCondition",s); 5 for (Student s1 : result) { 6 System.out.println("s1 id=" + s1.getStuId()); 7 System.out.println("s1 name=" + s1.getStuName()); 8 System.out.println("s1 Birthdate=" + s1.getStuBirthdate()); 9 } 10 session.close(); 11 }
測試
1 public static void main(String[] args) throws Exception { 2 //創建要保存的學生信息 3 Student s = new Student(); 4 s.setStuName("zhou"); 5 s.setStuBirthdate(new SimpleDateFormat("yyyy-MM-dd").parse("1991-1-12")); 6 7 StudentDao sdao = new StudentDaoImpl(fac); 8 sdao.testQuery6(s); 9 }
2 choose元素
choose元素相當於java語句的if … else if …else語句
1 <!-- 動態SQL:choose標簽 --> 2 <select id="queryByCondition2" parameterType="student " resultMap="BaseResultMap"> 3 select * from student where 1=1 4 <choose> 5 <when test="stuName != null and stuName != ''"> 6 and stu_name=#{stuName} 7 </when> 8 <when test="stuBirthdate != null"> 9 and stu_birthdate=#{stuBirthdate} 10 </when> 11 <otherwise> 12 and stu_phone=#{stuPhone} 13 </otherwise> 14 </choose> 15 </select>
3 WHERE元素
使用where元素會自動根據條件的個數增刪where語句and運算符,所以不需要寫where 1=1之類的語句
1 <!-- 動態SQL:where標簽 --> 2 <select id="queryByCondition3" parameterType="student " resultMap="BaseResultMap"> 3 select * from student 4 <where> 5 <if test="stuName != null and stuName != ''"> 6 and stu_name=#{stuName} 7 </if> 8 <if test="stuBirthdate != null"> 9 and stu_birthdate=#{stuBirthdate} 10 </if> 11 <if test="stuPhone != null and stuPhone != ''"> 12 and stu_phone=#{stuPhone} 13 </if> 14 </where> 15 </select>
4 Trim元素
trim元素的主要功能是可以在自己包含的內容前加上某些前綴,也可以在其后加上某些后綴,與之對應的屬性是prefix和suffix;可以把包含內容的首部某些內容覆蓋,即忽略,也可以把尾部的某些內容覆蓋,對應的屬性是prefixOverrides和suffixOverrides
1 <!-- 動態SQL:trim標簽 --> 2 <select id="queryByCondition4" parameterType="student " resultMap="BaseResultMap"> 3 select * from student 4 <trim prefix="where" prefixOverrides="and|or"> 5 <if test="stuName != null and stuName != ''"> 6 and stu_name=#{stuName} 7 </if> 8 <if test="stuBirthdate != null"> 9 and stu_birthdate=#{stuBirthdate} 10 </if> 11 <if test="stuPhone != null and stuPhone != ''"> 12 or stu_phone=#{stuPhone} 13 </if> 14 </trim> 15 </select>
5 foreach元素
foreach的主要用在構建in條件中,它可以在SQL語句中進行迭代一個集合。foreach元素的屬性主要有item,index,collection,open,separator,close。item表示集合中每一個元素進行迭代時的別名,index指定一個名字,用於表示在迭代過程中,每次迭代到的位置,open表示該語句以什么開始,separator表示在每次進行迭代之間以什么符號作為分隔符,close表示以什么結束,在使用foreach的時候最關鍵的也是最容易出錯的就是collection屬性,該屬性是必須指定的,但是在不同情況下,該屬性的值是不一樣的,主要有以下3種情況。
- 如果傳入的是單參數且參數類型是一個List的時候,collection屬性值為list
- 如果傳入的是單參數且參數類型是一個array數組的時候,collection的屬性值為array
- 如果傳入的參數是多個的時候,我們就需要把它們封裝成一個Map了,當然單參數也可以封裝成map,實際上如果你在傳入參數的時候,在MyBatis里面也是會把它封裝成一個Map的,map的key就是參數名,所以這個時候collection屬性值就是傳入的List或array對象在自己封裝的map里面的key
Mapper.xml
1 <!-- 動態SQL:傳入Array數組 --> 2 <select id="queryByInArray" resultMap="BaseResultMap"> 3 select * from student 4 <if test="array.length>0"> 5 where stu_id in 6 <foreach collection="array" index="i" item="stuId" open="(" close=")" separator=","> 7 #{stuId} 8 </foreach> 9 </if> 10 </select> 11 <!-- 動態SQL:傳入List集合 --> 12 <select id="queryByInList" resultMap="BaseResultMap"> 13 select * from student 14 <if test="list.size()>0"> 15 where stu_id in 16 <foreach collection="list" index="i" item="stuId" open="(" 17 close=")" separator=","> 18 #{stuId} 19 </foreach> 20 </if> 21 </select> 22 <!-- 動態SQL:傳入Map集合包含List集合 --> 23 <select id="queryByInMap" resultMap="BaseResultMap"> 24 select * from student 25 <if test="ids.size()>0"> 26 where stu_id in 27 <foreach collection="ids" index="i" item="stuId" open="(" 28 close=")" separator=","> 29 #{stuId} 30 </foreach> 31 </if> 32 </select>
DaoImpl.java
1 @Override 2 public void testQuery7(){ 3 SqlSession session = fac.openSession(); 4 int[] ids = new int[]{2}; 5 List<Student> list = session.selectList("student.queryByInArray",ids); 6 for (Student item : list) { 7 System.out.println(item); 8 } 9 session.close(); 10 } 11 @Override 12 public void testQuery8(){ 13 SqlSession session = fac.openSession(); 14 List ids = new ArrayList(); 15 ids.add(2); 16 ids.add(3); 17 ids.add(4); 18 List<Student> list = session.selectList("student.queryByInList",ids); 19 for (Student item : list) { 20 System.out.println(item); 21 } 22 session.close(); 23 } 24 @Override 25 public void testQuery8(){ 26 SqlSession session = fac.openSession(); 27 List ids = new ArrayList(); 28 ids.add(2); 29 ids.add(3); 30 Map map = new HashMap(); 31 map.put("ids", ids); 32 List<Student> list = session.selectList("student.queryByInMap",map); 33 for (Student item : list) { 34 System.out.println(item); 35 } 36 session.close(); 37 }
6 set元素
set元素主要是用在更新操作的時候,它的主要功能和where元素其實是差不多的,主要是在包含的語句前輸出一個set,然后如果包含的語句是以逗號結束的話將會把該逗號忽略,如果set包含的內容為空的話則會出錯。有了set元素我們就可以動態的更新那些修改了的字段。
1 <!-- 動態SQL:set更新 --> 2 <update id="updateByCondition" parameterType="student"> 3 update student 4 <set> 5 <if test="stuName!=null and stuName!=''"> 6 stu_name=#{stuName}, 7 </if> 8 <if test="stuBirthdate!=null"> 9 stu_birthdate=#{stuBirthdate}, 10 </if> 11 <if test="stuPhone!=null and stuPhone!=''"> 12 stu_phone=#{stuPhone} 13 </if> 14 </set> 15 where stu_id=#{stuId} 16 </update>
7 <SQL>和<include>
可以編寫一些語句片段<SQL>標簽,然后在其他語句標簽匯中用<include>引用,這樣可以是SQL語句片段得到重用
示例:
<!-- SQL片段 --> <SQL id="SQL_select"> select * </SQL> <SQL id="SQL_count"> select count(*) </SQL> <!-- 包含SQL片段 --> <select id="query6" resultMap="BaseResultMap"> <include refid="SQL_select"/> from student </select> <select id="query7" resultType="java.lang.Integer"> <include refid="SQL_count"/> from student </select>