动态SQL是MyBatis的强大特性之一,MyBatis3采用了功能强大的基于OGNL的表达式来完成动态SQL,它消除了之前版本中需要了解的大多数元素,使用不到原来一半的元素就能完成所需工作。
MyBatis动态SQL中的主要元素,如表1所示。
表1 MyBatis的动态SQL元素
| 元素 | 说明 |
|---|---|
| 判断语句,用于单条件分支判断 | |
| 相当于Java中的switch...case...default语句,用于多条件分支判断 | |
| 辅助元素,用于处理一些SQL拼装、特殊字符问题 | |
| 循环语句,常用于in语句等列举条件中 | |
| 从OGNL表达式中创建一个变量,并将其绑定到上下文,常用于模糊查询的sql中 |
表1列举了MyBatis动态SQL的一些主要元素,并分别对其作用进行了简要介绍。
动态sql,查询条件不确定有多少可以用HashMap来存储,也可以用一个类来封装所有可能的条件
| 用HashMap 优点:无需单独定义查询条件类 缺点:向HashMap中添加数据时的key要和sql语句查询时一致 | 用一个查询条件类 优点:在sql语句获取参数时直接使用属性名,不用担心命名不一致问题 缺点:需要单独定义一个类 |
| 无 | @Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class StudentSearchCondition {
private String gender;
//整形使用int在判断时不能用null,而用0
//使用Integer对象类型时用null
private Integer age;
private String name;
} |
//动态sql,查询条件不确定可以用HashMap public List | //动态sql,查询条件不确定也可以用一个类来封装所有可能的条件 public List |
HashMap | StudentSearchCondition params=new StudentSearchCondition();
params.setGender("女");
params.setAge(18);
StudentDAO studentDAO=mybatisUtils.getMapper(StudentDAO.class);
List |
| |
2.
在MyBatis中,
3.
映射文件中编写的SQL后面都加入了“where 1=1”的条件防止直接拼接and关键字出现异常,使用where标签可以解决这个问题,
and sgender=#{gender} and sage=#{age}
and sgender=#{gender} and sage=#{age}
MyBatis中已经提供了一种用于数组和集合循环遍历的方式,那就是使用
//动态sql,查询年龄是18,19,20的学生
public List searchStudentByAge(List age);
@Test
public void searchStudentByAge() {
List ages = new ArrayList<>();
ages.add(18);
ages.add(19);
ages.add(20);
StudentDAO studentDAO=mybatisUtils.getMapper(StudentDAO.class);
List studentList=studentDAO.searchStudentByAge(ages);
studentList.forEach(System.out::println);
}
在上述代码中,使用了
● item:配置的是循环中当前的元素。
● index:配置的是当前元素在集合的位置下标。
● collection:配置的list是传递过来的参数类型(首字母小写),它可以是一个array、list(或collection)、Map集合的键、POJO包装类中数组或集合类型的属性名等。
● open和close:配置的是以什么符号将这些集合元素包装起来。
● separator:配置的是各个元素的间隔符。
注意:
你可以将任何可迭代对象(如列表、集合等)和任何的字典或者数组对象传递给
4.在使用
时最关键也是最容易出错的就是collection属性,该属性是必须指定的,而且在不同情况下,该属性的值是不一样的。主要有以下3种情况:
如果传入的是单参数且参数类型是一个数组或者List的时候,collection属性值分别为array和list(或collection);
如果传入的参数是多个的时候,就需要把它们封装成一个Map了,当然单参数也可以封装成Map集合,这时候collection属性值就为Map的键。
如果传入的参数是POJO包装类的时候,collection属性值就为该包装类中需要进行遍历的数组或集合的属性名。
所以在设置collection属性值的时候,必须按照实际情况配置,否则程序就会出现异常。
当多个条件都成立时,只根据第一个成立的条件查询;当一个条件成立时就根据这一个查询;当没有条件成立时根据otherwise查询
5.
//更新学生信息,只更新某个字段而非全部重写
public int updateStudent(Student student);
@Test
public void updateStudent() {
StudentDAO studentDAO=mybatisUtils.getMapper(StudentDAO.class);
Student student= new Student();
student.setStuId(8021);
student.setStuAge(21);
student.setStuName("小华");
int i=studentDAO.updateStudent(student);
System.out.println(i);
}
update students where sid=#{stuId} sname=#{stuName}, sgender=#{stuGender}, sage=#{stuAge},
6.如果
元素内包含的内容都为空,则会出现SQL语法错误。所以在使用 元素进行字段信息更新时,要确保传入的更新字段不能都为空。
在进行模糊查询编写SQL语句的时候,如果使用“${}”进行字符串拼接,则无法防止SQL注入问题;如果使用concat函数进行拼接,则只针对MySQL数据库有效;如果使用的是Oracle数据库,则要使用连接符号“||”。这样,映射文件中的SQL就要根据不同的情况提供不同形式的实现,这显然是比较麻烦的,且不利于项目的移植。为此,MyBatis提供了
MyBatis的
上述配置代码中,使用
测试:
//模糊查询,防止sql注入
public List searchStudentByName(String name);
@Test
public void searchStudentByName() {
StudentDAO studentDAO=mybatisUtils.getMapper(StudentDAO.class);
List studentList=studentDAO.searchStudentByName("刚");
studentList.forEach(System.out::println);
}



