动态sql是Mybatis的强大特性之一,能够复用sql片段,拼接sql串。常用的动态sql标签有:<where> <if> <choose> <when> <foreach>等
比如这样一句sql查询语句:select stuno,stuname,stuage from student2 where stuname=#{stuName}
使用动态sql的方式:
<select id="queryStuByNOrAWithSQLTag" parameterType="student" resultType="student">
select stuno,stuname,stuage from student2
<where>
<if test="stuName != null and stuName!='' ">
and stuname=#{stuName}
</if>
<if test="stuAge !=null and stuAge!=0">
and stuage=#{stuAge}
</if>
</where>
</select>
使用上面的方式,如果传进来stuname的值,if标签就会判断该值是否为空,不为空再赋值给stuname。另外需要注意一点, <if test="stuName != null and stuName!='' "> ,里面stuName为student类中的属性名,需要区分大小写,还有parameterType="student",是对象类型,所以下面的#{},里面要填该student对象类型的属性值。where标签会自动处理第一个if标签的and或者or,所以最后拼的sql为:
select stuno,stuname,stuage from student2 where stuname=#{stuName} and stuage=#{stuAge}
foreach标签的使用:
foreach可以迭代的类型:数组、对象数组、集合、属性(Grade类中的 list<Integer> ids 属性)
遍历属性(Grade类中的 list<Integer> ids 属性):
查询学号为1,2,3的学生信息,sql为:select stuno,stuname from student2 where stuno in(1,2,3)
mapper.xml中:
<!-- 将多个元素值放入对象的属性中 -->
<select id="queryStudentsWithNosInGrade" parameterType="grade" resultType="student">
select * from student2
<where>
<if test="stuNos != null and stuNos.size>0">
<foreach collection="stuNos" open=" stuno in (" close=")" item="sNo" separator=",">
#{sNo}
</foreach>
</if>
</where>
</select>
for(String name:names[])
上面的sql中,其实就是在if标签中加了foreach进行迭代遍历,collection表示对象中的集合属性,也就是grade类中的list属性stuNos,类似上面中的names[],open和close分别表示遍历的集合的左右两边,open="stuno in(" close=")",item表示遍历出来的每个元素,类似上面中的name,item="sNo",item其实就是定义变量,就跟name一样,我们自己定的一个名字,真正用到这个变量是在下面,也就是迭代,#{sNo},获取变量的值。separator表示每个元素中间的分隔符。
遍历数组:
<!-- 将多个元素值放入数组中 -->
<select id="queryStudentsWithArray" parameterType="int[]" resultType="student">
select * from student2
<where>
<if test="array != null and array.length>0">
<foreach collection="array" open=" stuno in (" close=")" item="number" separator=",">
#{number}
</foreach>
</if>
</where>
</select>
上面遍历int[]数组,foreach中写法和之前的一样,重要的区别在于collection,规定为array。即输入参数为简单类型的数组,入string[] int[]这种,必须用arrary代替该数组。
遍历集合:
<!-- 将多个元素值放入list中 -->
<select id="queryStudentsWithList" parameterType="list" resultType="student">
select * from student2
<where>
<if test="list != null and list.size>0">
<foreach collection="list" open=" stuno in (" close=")" item="number" separator=",">
#{number}
</foreach>
</if>
</where>
</select>
注意,这种遍历集合和第一种不同,第一种遍历的是对象的属性,只是这个属性为集合类型。而这种遍历集合跟对象类型无关,并不是某个类的某个属性。这种遍历集合的方式,里面全部写list.
遍历对象数组:
<!-- 将多个元素值放入对象数组中Student[] students={student0,student1,student2} 每个student包含一个stuno-->
<select id="queryStudentsWithObjectArray" parameterType="Object[]" resultType="student">
select * from student2
<where>
<if test="array != null and array.length>0">
<foreach collection="array" open=" stuno in (" close=")" item="student" separator=",">
#{student.stuNo}
</foreach>
</if>
</where>
</select>
测试类中:
StudentMapper studentMapper = session.getMapper(StudentMapper.class) ;
Student student0=new Student();
student0.setStuNo(1);
Student student1=new Student();
student1.setStuNo(2);
Student student2=new Student();
student2.setStuNo(65);
Student[] students= {student0,student1,student2};
List<Student> list= studentMapper.queryStudentsWithObjectArray(students) ;
System.out.println(list);
session.close();
这种遍历对象数组和第二种不同,第二种是遍历简单类型的数组,这种是遍历对象类型数组。需要注意一下几点:
1.parameterType="Object[]"
2.下面的还是用array
3.item="student",传的对象
4.#{student.stuNo},里面写的是对象的属性
sql片段:可以将需要复用的sql提取出来,类似于java当中定义一个方法,可以被多个类使用
<sql id="objectArrayStunos">
<where>
<if test="array != null and array.length>0">
stuno in
<foreach collection="array" open="(" close=")" item="student" separator=",">
#{student.stuNo}
</foreach>
</if>
</where>
</sql>
<select id="queryStudentsWithObjectArray" parameterType="Object[]" resultType="student">
select * from student2
<include refid="objectArrayStunos"></include>
</select>
上面,我们把where语句后面的提取出来,用<sql>标签提取,取一个唯一标识符 id,然后在里面写具体的sql。想要引用这段sql时,就使用include标签,通过refid=sql标签中的id来引用。如果sql片段在a.xml中,引用在b.xml中,则refid=a的namespace+sql片段的id值。