动态 SQL,主要用于解决查询条件不确定的情况:在程序运行期间,根据用户提交的查 询条件进行查询。
提交的查询条件不同,执行的 SQL 语句不同。若将每种可能的情况均逐一 列出,对所有条件进行排列组合,
将会出现大量的 SQL 语句。此时,可使用动态 SQL 来解 决这样的问题。
动态 SQL,即通过 MyBatis 提供的各种标签对条件作出判断以实现动态拼接 SQL 语句。
这里的条件判断使用的表达式为 OGNL 表达式。常用的动态 SQL 标签有<if>、<where>、<choose/>、<foreach>等。
有一个有意思的发现是,MyBatis 的动态 SQL 语句,与 JSTL 中的语句非常相似
1 <mapper namespace="com.mybatis.dao.StudentDAO"> 2 <!-- parameterType 可以省略 --> 3 4 <!-- if标签 传入的是Student 对象,可以直接对它的属性进行判断 --> 5 <select id="selectStudentsIf" resultType="com.mybatis.model.Student"> 6 select * from student where 1 = 1 7 <if test="name != null and name != ''"> 8 and name like '%' #{name} '%' 9 </if> 10 <if test="age>0"> 11 and age > #{age} 12 </if> 13 </select> 14 15 <!-- where 标签 ,会帮你去掉 and, 但是不会帮你加上and--> 16 <select id="selectStudentsWhere" resultType="com.mybatis.model.Student"> 17 select * from student 18 <where> 19 <if test="name != null and name != ''"> 20 and name like '%' #{name} '%' 21 </if> 22 <if test="age>0"> 23 and age > #{age} 24 </if> 25 </where> 26 </select> 27 28 <!-- choose 标签 (switch) --> 29 <select id="selectStudentsChoose" resultType="com.mybatis.model.Student"> 30 select * from student 31 <where> 32 <!-- choose标签 类似于 switch,多个when,就是多个case,只会执行一个when otherwise 相当于 default --> 33 <choose> 34 <when test="name != null and name != ''"> 35 and name like '%' #{name} '%' 36 </when> 37 38 <when test="age>0"> 39 and age > #{age} 40 </when> 41 42 <otherwise> 43 1 = 2 44 </otherwise> 45 </choose> 46 </where> 47 </select> 48 49 <!-- 遍历Object[] ,Array 的 别名是 array ,所以 传入的参数是数组类型时,需使用别名 来指向 这个参数对象 --> 50 <select id="selectStudentsForeachArray" resultType="com.mybatis.model.Student"> 51 select * from student 52 <if test="array != null and array.length > 0"> 53 where id in 54 <foreach collection="array" item="id" open="(" separator="," close=")"> 55 #{id} 56 </foreach> 57 </if> 58 </select> 59 60 <!-- 遍历 List<Integer> List的别名 是 list,--> 61 <select id="selectStudentsForeachList" resultType="com.mybatis.model.Student"> 62 select * from student 63 <if test="list != null and list.size > 0"> 64 where id in 65 <foreach collection="list" item="id" open="(" separator="," close=")"> 66 #{id} 67 </foreach> 68 </if> 69 </select> 70 71 <!-- 遍历 List<Student> 遍历出来的一个一个Student ,#{} 可以读到对象的属性 --> 72 <select id="selectStudentsForeachList2" resultType="com.mybatis.model.Student"> 73 select <include refid="selectColumns"></include> from student 74 <if test="list != null and list.size > 0"> 75 where id in 76 <foreach collection="list" item="student" open="(" separator="," close=")"> 77 #{student.id} 78 </foreach> 79 </if> 80 </select> 81 82 <!-- 定义SQL 片段,以便其他SQL标签复用 好处:修改时可以统一修改,但是 可读性很差 --> 83 <sql id="selectColumns"> 84 * 85 </sql> 86 87 </mapper>
注意:在 mapper 的动态 SQL 中若出现大于号(>)、小于号(<)、大于等于号(>=),小于等 于号(<=)等符号,
最好将其转换为实体符号。否则,XML 可能会出现解析出错问题。
特别是对于小于号(<),在 XML 中是绝对不能出现的。否则,一定出错。(其他只是可能出错)