--------------------------------MaBatis动态sql--------------------------
1)动态SQL基于OGNL的表达式,可以方便的在SQL语句中实现某些逻辑,用于实现动态SQL的元素如下:
(1)if:利用if实现简单的条件选择。
(2)choose(when,otherwise):相当于Java中的switch语句。通常与when和otherwise搭配。
(3)where :简化SQL语句中where的条件判断,主要用来简化SQL语句中的where条件判断,并能智能的处理and和 or,不必要担心关键字导致的语法错误。
(4)set:解决动态更新语句
(5)trim:可以灵活的去除多余的关键字。
(6)foreach:迭代一个集合,通常用于in条件
2)
现在前台有个表单! 表单中有三项条件 来查询 符合条件的学生! 01.根据学生姓名查询 02.根据老师姓名查询 03.根据年级名称查询 针对于上述的情况,我们发现三个查询条件 不在同一个表中! 第一种情况: 把学生姓名,老师姓名,年级名称封装成一个Map集合 Map<String.Object> map=new HashMap<String,Object>(); //把三个条件放进map map.put("studentName",学生姓名); map.put("teacherName",老师姓名); map.put("gradeName",年级名称); //调用dao层方法 dao.xxx(map); 然后去mapper.xml文件中执行sql语句 select s.name,s.id,s.age from student s,teacher t,grade g where s.tId=t.id and s.gId=g.id and s.name=#{studentName} //开始使用map中的key and t.name=#{teacherName} and g.name=#{gradeName} 第二种情况: 用户可以传递几个参数,我们在方法定义时就书写几个形参! 在接口中书写方法 List<Student> selectStduentsByCondition(String stuName,String teacherName,String gradeName); 在mapper.xml文件中书写sql select s.name,s.id,s.age from student s,teacher t,grade g where s.tId=t.id and s.gId=g.id and s.name=#{0} //开始使用参数的下标 and t.name=#{1} and g.name=#{2} 总结#{}中可以存放的内容 01. 当参数是对象的时候,存放的是对象的属性 02. 存放map时的注意点 001.当参数是map集合时,存放的是map的key 002.如果map的value是对象时,存放的是对象的属性 03.如果传递一个参数,存放的是占位符 04.如果传递多个参数,存放的是参数对应的下标,从0开始
<mapper namespace="com.xdf.dao.StudentDao"> <!--必须是对应的dao接口的全类名--> <!-- 我们在前台表单中 有 三个输入框! 用户输入了几个???我们不知道 #{stuName}#{stuAge} 必须是map集合中的key <select id="selectStduentsByMap" resultType="Student"> select id,name,age from student where name like concat('%',#{stuName},'%') and age>#{stuAge} </select> --> <select id="selectStduentsByMap" resultType="Student"> select id,name,age from student where name like concat('%',#{stuName},'%') and age>#{stuAge} AND id>#{student.id} </select> <!--按照参数的下标进行封装 下标从0开始--> <select id="selectStduentsByCondition" resultType="Student"> select id,name,age from student where name like concat('%',#{0},'%') and age>#{1} </select> </mapper>
上面都是写死的。没用动态标签,看下面
<mapper namespace="com.xdf.dao.StudentDao"> <!--必须是对应的dao接口的全类名--> <!-- 01.用户传递一个Student对象 但是我们不知道用户对那些属性赋了值 注意点 特殊字符的使用 && (逻辑与) 必须换成 (and) 或者 (&) where 1=1 每次拼接查询都会 执行 影响性能 --> <select id="selectStudentsByIf" resultType="Student"> SELECT id,name,age from student where 1=1 <if test="name!=null and name!=''"> and name like concat('%',#{name},'%') </if> <if test="age > 0"> and age > #{age} </if> </select> <!--where 标签 替换where 1=1--> <select id="selectStudentsByWhere" resultType="Student"> SELECT id,name,age from student <where> <if test="name!=null and name!=''"> and name like concat('%',#{name},'%') </if> <if test="age > 0"> and age > #{age} </if> </where> </select> <!-- choose标签 类似java中的switch 01.当我们的年龄不为空 按照年龄查询 02.当我们的姓名不为空 按照姓名查询 03.如果都会空 执行otherwise 如果没有otherwise标签,会查询所有 04.如果多个条件满足,执行第一个满足的when 如果条件只允许执行一个 就是用choose 因为值执行一个sql 所以不需要加and 想多个条件执行,使用if 因为有多个sql需要拼接 所以 不能省略and 在mybatis中 底层不会给我们生成and --> <select id="selectStudentsByChoose" resultType="Student"> SELECT id,name,age from student <where> <choose> <when test="name!=null and name!=''"> name like concat('%',#{name},'%') </when> <when test="age > 0"> age>#{age} </when> <otherwise> 1!=1 </otherwise> </choose> </where> </select> <!-- foreach 遍历数组 我们之前在mysql中查询的语句 SELECT id,NAME,age FROM student WHERE id IN (12,13,14) 问题?? 01.我们知道用户输入的是12,13,14,吗??? 02.12,13,14是动态获取的 是dao中方法的参数 int [] nums 03.nums的每个元素 就是 12,13,14 04.用户是不是有可能一个值都没有传入 05.只要是数组 在mybatis对应的值就是array --> <select id="selectStudentsByForeachArray" resultType="Student"> SELECT id,NAME,age FROM student <if test="array.length>0"> /*证明用户有值传入*/ where id IN /*(12,13,14) 动态的拼接*/ <foreach collection="array" item="varId" open="(" separator="," close=")"> #{varId} </foreach> </if> </select> <!--遍历 List集合 在mybatis对应的值就是list--> <select id="selectStudentsByForeachList" resultType="Student"> SELECT id,NAME,age FROM student <if test="list.size>0"> where id IN <foreach collection="list" item="varId" open="(" separator="," close=")"> #{varId} </foreach> </if> </select> <!--遍历 Student集合 --> <select id="selectStudentsByForeachStudent" resultType="Student"> SELECT id,NAME,age FROM student <if test="list.size>0"> where id IN <foreach collection="list" item="stu" open="(" separator="," close=")"> #{stu.id} /*必须是对象中的属性*/ </foreach> </if> </select> <!--遍历 map集合 map集合在mybatis中没有设置对应的值 myMap就是我们dao层方法的@Param("myMap") 遍历myMap.keys 就是获取map集合中的所有key的集合 --> <select id="selectStudentsByForeachMap" resultType="Student"> <include refid="seleteStudents"/> where id IN <if test="myMap.keys.size>0"> <foreach collection="myMap.keys" item="mapKey" open="(" separator="," close=")"> #{mapKey} </foreach> </if> </select> <!-- sql片段: 提取mapper文件中所有的sql公共部分 --> <sql id="seleteStudents"> SELECT id,NAME,age FROM student </sql> </mapper>
4)使用if+trim实现多条件查询
trim 属性
prefix:前缀覆盖并增加其内容
suffix:后缀覆盖并增加其内容
prefixOverrides:前缀判断的条件
suffixOverrides:后缀判断的条件
<where> <if> <if>标签单独使用,如下 <select id="selectSudent" parameterType="String" resultType="java.util.List"> SELECT * FROM student <if test="name!=null and name!=''"> WHERE name like CONCAT('%',#{name},'%') </if></select> 如果name为空或空串 则进行全部查询,效率会下降 当进行多条件下查询是,<where> <if> 可以提高查询速度 和优化查询语句 <select id="selectSudent" parameterType="String" resultType="java.util.List"> SELECT name,sex FROM student <where> <if test="name!=null and name!=''"> name like CONCAT('%',#{name},'%') </if> <if test="sex!=null and sex!=''"> AND sex=#{sex} </if> </where></select> <set> <if> 使用 <update id="updateStudent" parameterType="com.frank.Student"> UPDATE student <set> <if test="name!=null and name!=''"> name= #{name}, </if> <if test="sex!=null and sex!=''"> sex=#{sex} </if> </set> WHERE no=#{no} </update> <trim> <if> 我个人感觉<trim>标签就是<where><set>结合 他同时具有两者的功能 <select id="selectSudent" parameterType="String" resultType="java.util.List"> SELECT name,sex FROM student <trim prefix="WHERE" prefixOverrides="AND|OR"> <if test="name!=null and name!=''"> name like CONCAT('%',#{name},'%') </if> <if test="sex!=null and sex!=''"> AND sex=#{sex} </if> </trim> </select> <update id="updateStudent" parameterType="com.frank.Student"> UPDATE student <trim prefix="SET" suffixOverrides=","> <if test="name!=null and name!=''"> name= #{name}, </if> <if test="sex!=null and sex!=''"> sex=#{sex} </if> </trim> WHERE no=#{no} </update>