系列文章目录
MyBatis01:创建、运行、测试一个mybatis项目
MyBatis02:使用MyBatis查询数据
MyBatis03:嵌套查询、嵌套结果、延迟加载
MyBatis04:动态SQL
MyBatis05:类型转换器
MyBatis06:分页插件、MyBatis配置文件中的标签
MyBatis07:MyBatis注解
文章目录
前言
下面内容主要讲解什么是动态SQL,动态SQL的优势,以及如何使用mybatis框架的一些标签元素,来实现动态SQL。
一、什么是动态SQL
动态SQL就是动态拼接SQL语句。当SQL语句满足某种条件时,才拼接该SQL语句;不满足某种条件时,就不拼接该SQL语句。
二、动态SQL的优势
例如我们要做批量删除,由于要删除的数据的条数不确定,我可以采取这样两种方法来实现删除数据。第一种,在service层调用dao层的方法,每次删除一条数据。第二种,直接在dao层做判断,删除符合条件的所有数据。第一种方法的问题就在于,每调用一次dao层的方法,就需要连接一次数据库。第二种方法只需要连接一次数据库,就可以删除需要删除的全部数据。当数据量大的时候,两种方法的优劣就非常明显了。第二种方法利用的就是动态SQL。
三、动态SQL的标签元素
注意:
①动态SQL标签里不用写ognl表达式,直接写key即可。但SQL语句的字符串里还是需要写ognl表达式的。
②基本数据类型的封装类型在判断时,不仅要判断是否为null,换需要判断是否为默认值
1. if元素
1.1 语法
<if test="判断条件">
SQL语句
</if>
if元素是用来对数据添加判断的,test是判断条件,if标签里可以添加SQL语句。
1.2 案例
根据班级编号和学生姓名模糊查询学生信息
dao接口:
List<Student> selectByClassidAndName(@Param("classid") Integer classid, @Param("name") String name);
映射代码:
<select id="selectByClassidAndName" resultType="com.bean.Student">
select * from student where 1 = 1
<if test="classid != null and classid > 0">
and classid = #{classid}
</if>
<if test="name != null and name != ''">
and name like "%"#{name}"%"
</if>
</select>
只有条件成立时,才会拼接对应的SQL语句
2. choose、when、otherwise元素
2.1 语法
<choose>
<when test="判断条件1">SQL语句</when>
<when test="判断条件2">SQL语句</when>
<otherwise>SQL语句</otherwise>
</choose>
choose、when、otherwise元素是用来实现多重if判断的。
3. where元素
3.1 语法
<where>
其他标签或SQL语句
</where>
where元素相当于SQL语句的where,但比where更加智能,通过案例来讲解。
3.2 案例
<select id="selectByClassidAndName" resultType="com.bean.Student">
select * from student
<where>
<if test="classid != null and classid > 0">
and classid = #{classid}
</if>
<if test="name != null and name != ''">
and name like "%"#{name}"%"
</if>
</where>
</select>
这里使用了where元素。在查询条件时,如果条件成立,会自动去除条件里的and,如果所有条件不成立,在查询语句 select * from student
的后面也不会添加where。
4. trim元素
4.1 语法
<trim prefix="要添加前缀" suffix="要添加的后缀" prefixOverrides="前缀如果有该内容,就覆盖掉" suffixOverrides="后缀如果有该内容,就覆盖掉">
其他标签或SQL语句
</trim>
trim是用来修剪字符串的
4.2 案例
<select id="selectByClassidAndName" resultType="com.bean.Student">
select * from student
<trim prefix="where" prefixOverrides="and">
<if test="classid != null and classid > 0">
and classid = #{classid}
</if>
<if test="name != null and name != ''">
and name like "%"#{name}"%"
</if>
</trim>
</select>
通过班级id和学生姓名查询学生。解释一下这个代码:
在查询语句至少有一个满足的情况下,才追加where。前缀中如果是and,就把and覆盖掉,否则会出现 where and
这样的情况。
5. set元素
5.1 语法
<set>
其他标签或SQL语句
</set>
set元素相当于SQL语句的set,但比set更智能。
5.2 案例
<update id="updateByPrimaryKeySelective">
update student
<set>
<if test="name != null">
name = #{name},
</if>
<if test="sex != null">
sex = #{sex},
</if>
<if test="birthday != null">
birthday = #{birthday},
</if>
<if test="age > 0">
age = #{age},
</if>
<if test="classid > 0">
classid = #{classid}
</if>
</set>
where id = #{id}
</update>
至少有一个条件满足的时候,update student
后才会有set。而且set标签会自动去掉语句末尾的逗号
6. foreach元素
6.1 语法
<foreach collection="list" item="id" open="(" separator="," close=")">
#{id}
</foreach>
属性 | 含义/作用 |
---|---|
collection | 获取要循环的数组或集合,通过key获取 |
item | collection迭代一个元素就赋给item一个值 |
open | 循环开始要添加的内容 |
separator | 每次循环用什么分隔 |
close | 循环结束要添加什么内容 |
foreach就是用来循环的
6.2 批量删除
PetMapper.java
//批量删除
int deleteBatch(List<Integer> ids);
PetMapper.xml
<delete id="deleteBatch">
delete from student
<where>
id in
<foreach collection="list" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</where>
</delete>
如果id在list集合里,那么就删除该编号的学生
PetService.java
int deleteBatch(List<Integer> ids);
PetServiceImpl.java
@Override
public int deleteBatch(List<Integer> ids) {
return this.petMapper.deleteBatch(ids);
}
PetTest
@Test
public void deleteBatch() {
List<Integer> ids = new ArrayList<>();
ids.add(5);
ids.add(6);
System.out.println(this.petService.deleteBatch(ids));
}
collection补充: 要做foreach的对象,作为入参时,List对象默认用"list"代替作为键,数组对象有"array"代替作为键,Map对象没有默认的键。当然在作为入参时可以使用@Param(“keyName”)来设置键,设置keyName后,list,array将会失效。
forEach参考:
mybatis之foreach用法
补充
- 动态SQL的参数需要使用@Param标签来设置key,否则会报找不到getter错误
- 日期类型不能和空字符串比较
- 更新数据时,set 属性=xxx 需要用「逗号」分割,别忘了
- 批量删除时的list集合是通过参数获取的
总结
今天主要学习了动态SQL。了解了动态SQL的优势,以及学习和使用动态SQL的标签元素,以及介绍了相应的案例来加深理解。