MyBatis的动态SQL主要包括if,choose(when,otherwise),where,set,foreach,先来看看if:
<select id="queryTeacherByStudentNameAddSex" parameterType="com.zengyg.myibatis.dto.StudentInfo"
resultMap="teacherResultUseJoin">
select t.teacher_id ,t.name ,t.sex,student_id,s.name as name_s,s.sex as sex_s
from teacher t left join student s on t.teacher_id =s.teacher_id
where t.teacher_id = #{teacherId}
<if test="sex != null and name != null">
and s.name = #{name}
and s.sex = #{sex}
</if>
</select>
if的test中可以是一个或者多个条件,可以是and也可以是or
choose(when,otherwise)的写法:
<select id="queryTeacherByStudentNameOrSex" parameterType="com.zengyg.myibatis.dto.StudentInfo"
resultMap="teacherResultUseJoin">
select t.teacher_id ,t.name ,t.sex,student_id,s.name as name_s,s.sex as sex_s
from teacher t left join student s on t.teacher_id =s.teacher_id
where t.teacher_id = #{teacherId}
<choose>
<when test="sex != null ">
and s.sex = #{sex}
</when>
<when test="name != null ">
and s.name = #{name}
</when>
<otherwise>
and s.student_id =3
</otherwise>
</choose>
</select>
和java 的switch case语句类似的写法,只要有一个条件满足则不在继续 执行下面的我when,如果所有条件都不满足,执行otherwise块,最后来看看foreach语句:
<select id="queryTeacherByStudentName" parameterType="com.zengyg.myibatis.dto.TeacherInfo"
resultMap="teacherResultUseJoin">
select t.teacher_id ,t.name ,t.sex,student_id,s.name as name_s,s.sex as sex_s
from teacher t left join student s on t.teacher_id =s.teacher_id
where s.name in
<foreach item="student" index="index" collection="list"
open="(" separator="," close=")">
#{student.name}
</foreach>
</select>
在使用foreach的时候最关键的也是最容易出错的就是collection属性,该属性是必须指定的,但是在不同情况 下,该属性的值是不一样的,主要有以下3种情况:
- 如果传入的是单参数且参数类型是一个List的时候,collection属性值为list
- 如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array
- 如果传入的参数是多个的时候,我们就需要把它们封装成一个Map了,当然单参数也可,此时collection属性值为map的key
list和array很好理解,对Map做一个说明,简单的示例代码,其中Java代码片段:
ArrayList<String> studentNames= new ArrayList<String>();
HashMap<String,Object> params = new HashMap<String,Object>();
params.put("nameList", studentNames);
params.put("sex", "F");
SqlMap代码片段:
<foreach item="name" index="index" collection="nameList"
open="(" separator="," close=")">
#{name}
</foreach>
Mybatis的动态SQL还有 where, set,用来处理查询时where后面紧跟动态SQL和update后紧跟动态SQL的问题,如下的select语句,当name为空sex不为空时,MyBatis会自动把sex前面的and 去掉,最后的查询语句类似: SELECT * FROM student where sex = ‘F’
<select id="*****" parameterType="Blog" resultType="***">
SELECT * FROM student
<where>
<if test="name != null">
name= #{nane}
</if>
<if test="sex != null">
and sex = #{sex}
</if>
</where>
</select>
同样set的场景用于update语句,set元素会动态前置SET关键字,而且也会消除任意无关的逗
<update id="*****" parameterType="****" resultType="***">
update student
<set>
<if test="name != null">
name= #{nane},
</if>
<if test="teacherId!= null">
teacher_id= #{teacherId},
</if>
<if test="sex != null">
sex = #{sex}
</if>
</set>
where student_id= #{studentId}
</update>
虽然Mybaties提供了where和set的解决方案,使sql可以正确执行,但为了程序的性能和稳健,业务层还是应该做必要的非空校验,不应该不带任何条件进行查询和更新