掌握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>