1、if
可以对传入的数据进行判断筛选。
测试类:
@Test
public void test01() {
Map<String, Object> map = new HashMap<>();
map.put("pname",null);
map.put("page", 20);
for(Student student : dao.selectStudentByIf(map)) {
System.out.println(student);
}
}
之前的多条件查询sql:
是对名字的模糊查询并且年龄小于某个数字。
<select id="selectStudentByIf" resultType="Student">
select id,name,age from student
where name like '%' #{pname} '%' and age < #{page}
</select>
可以看出sql语句是固定的,当其中两项条件中有某一项为null或者不存在时,查询结果就会出错。
这个时候在写sql语句的时候使用if标签,就可以避免缺少条件所导致的错误了。
使用if标签后的sql语句:
可以使用if添加判断条件,当参数不满足条件时,就不执行那一段sql。
<select id="selectStudentByIf" resultType="Student">
select id,name,age from student
where
<if test="pname != null and pname != ''">
name like '%' #{pname} '%'
</if>
<if test="page > 0">
and age < #{page}
</if>
</select>
这时就有个新的问题,当一个if不满足,满足第二个if时,拼接的sql就会是这个样子:
同样会导致查询失败。
可以在where语句后面添加一个不会影响sql运行的条件,并在两个if中的sql语句中都加上and。
<select id="selectStudentByIf" resultType="Student">
select id,name,age from student
where 1=1
<if test="pname != null and pname != ''">
and name like '%' #{pname} '%'
</if>
<if test="page > 0">
and age < #{page}
</if>
</select>
这样就可以保证,不管满足哪一个条件都可以完成查询。
实际上使用where标签就可以很轻松的解决这个问题。
2、where
测试类:
@Test
public void test02() {
Map<String, Object> map = new HashMap<>();
map.put("pname", null);
map.put("page", 20);
for(Student student : dao.selectStudentByWhere(map)) {
System.out.println(student);
}
}
映射文件:
<select id="selectStudentByWhere" resultType="Student">
select id,name,age from student
<where>
<if test="pname != null and pname != ''">
and name like '%' #{pname} '%'
</if>
<if test="page > 0">
and age < #{page}
</if>
</where>
</select>
使用了where标签之后,在if条件中的sql最好都加上and,这样即使只满足一个条件,也会自动省略and,不会出现sql拼接错误的情况。
3、choose
<select id="selectStudentByChoose" resultType="Student">
select id,name,age from student
<where>
<choose>
<when test="pname != null and pname != ''">
and name like '%' #{pname} '%'
</when>
<when test="page > 0">
and age > #{page}
</when>
<otherwise>
1 != 1
</otherwise>
</choose>
</where>
</select>
choose-when-otherwise表示多分支判断,类似于Java中的switch-case语句。
4、foreach
当要查询多条数据时使用。
使用foreach遍历数组:
测试类:
@Test
public void test04() {
Integer [] stu = {7,12,15};
for(Student student : dao.selectStudentByForeach(stu)) {
System.out.println(student);
}
}
查询出id为数组中定义的值的Student。
映射文件:
<select id="selectStudentByForeach" resultType="Student">
select id,name,age from student
<if test="array != null and array.length != 0">
<where>
id in
<foreach collection="array" open="(" close=")" separator=","
item="student">
#{student}
</foreach>
</where>
</if>
</select>
注意:此时传入的是数组,所以在foreach中collection属性值要写成array。
实际上foreach就是把传入过来的数组数据拼接成( , , , )这个形式。
item的值可以任意设置,最后foreach中#{}里要填写item设置的值。
使用foreach遍历List集合:
测试类:
@Test
public void test05() {
List<Integer> stu2 = new ArrayList();
stu2.add(7);
stu2.add(17);
stu2.add(18);
for(Student student : dao.selectStudentByForeach2(stu2)) {
System.out.println(student);
}
}
***映射文件:***`
<select id="selectStudentByForeach2" resultType="Student">
select id,name,age from student
<if test="list != null and list.size != 0">
<where>
id in
<foreach collection="list" open="(" close=")" separator=","
item="student">
#{student}
</foreach>
</where>
</if>
</select>
collection属性要填写为list。
使用foreach遍历对象:
测试类:
@Test
public void test06() {
List<Student> stu2 = new ArrayList();
Student student = new Student();
student.setId(2);
Student student2 = new Student();
student2.setId(17);
Student student3 = new Student();
student3.setId(18);
stu2.add(student);
stu2.add(student2);
stu2.add(student3);
for(Student students : dao.selectStudentByForeach3(stu2)) {
System.out.println(students);
}
}
映射文件:
<select id="selectStudentByForeach3" resultType="Student">
select id,name,age from student
<if test="list != null and list.size != 0">
<where>
id in
<foreach collection="list" open="(" close=")" separator=","
item="mystu">
#{mystu.id}
</foreach>
</where>
</if>
</select>
因为最后遍历出来的是对象,所以使用 对象.id 的方式获取到id。
5、sql
在实际开发中往往定义的实体类会比较多,如果要进行全部查询的话,在sql语句的编写上就有点困难,还容易出错,但是使用select * 又会增加查询时间,所以这时就可以用用sql片段,将出现机会较多、容易出错的sql语句单独的进行编写,什么地方需要用到,就直接对对其引用。
测试类:
@Test
public void test07() {//使用SQL片段的测试
List<Student> stu2 = new ArrayList();
Student student = new Student();
student.setId(2);
Student student2 = new Student();
student2.setId(17);
Student student3 = new Student();
student3.setId(18);
stu2.add(student);
stu2.add(student2);
stu2.add(student3);
for(Student students : dao.selectStudentBySQLFragment(stu2)) {
System.out.println(students);
}
}
测试的代码还是之前的代码,只不过调用的接口不同。
映射文件:
<!-- SQL片段的定义 -->
<!-- SQL片段可以定义SQL语句中任一片段 -->
<sql id="SQLFragment">
id,name,age
</sql>
<!-- SQL片段的使用 -->
<select id="selectStudentBySQLFragment" resultType="Student">
select <include refid="SQLFragment"/> from student
<if test="list != null and list.size != 0">
<where>
id in
<foreach collection="list" open="(" close=")" separator=","
item="mystu">
#{mystu.id}
</foreach>
</where>
</if>
</select>
在sql标签中可以定义sql语句中任一连续的片段。再使用include标签在sql语句中进行拼接。
这样做的优点就是降低代码冗余、增加可维护性、降低编写错误的发生。
缺点就是使sql语句的可读性变差。
最后总体的接口:
public interface IStudentDao {
List<Student> selectStudentByIf(Map<String, Object> map);//<if></if>
List<Student> selectStudentByWhere(Map<String, Object> map);//<where></where>
List<Student> selectStudentByChoose(Map<String, Object> map);//<choose></choose>
List<Student> selectStudentByForeach(Integer [] stu);//<foreach></foreach>
List<Student> selectStudentByForeach2(List<Integer> stu);
List<Student> selectStudentByForeach3(List<Student> stu);
List<Student> selectStudentBySQLFragment(List<Student> stu);//<sql></sql>
}