目录
1. 概念
动态 SQL 是相对于静态 SQL 的概念。静态 SQL 是指在编写程序时就已经确定下来的 SQL 语句,而动态 SQL 则允许根据程序运行时的数据或条件来生成不同的 SQL 语句。动态 SQL 的主要优势在于它提高了代码的灵活性和可维护性。
2. 动态SQL常用标签
(1)<if>标签
<if>
标签用于根据表达式的值决定是否包含某个 SQL 片段。
标签使用
<if test="condition">...</if>
说明:一般来说condition的值是 字段 !=null and 字段 != '' 。满足就执行 if 标签里的SQL语句,不满足就不执行,进入下一个 if 。
(2)<where>标签
<where>
标签用于自动处理 where 子句的开头,移除多余的AND
或OR
。
标签使用
<where>
...
</where>
说明:用于带条件的sql语句中,如果不加这个,在执行的过程中可能会出现多(少)and或者 or 的情况,加上的话自动管理 and 和 or 。
(3)<choose>
标签
类似于 Java 中的
switch
语句,用来选择一个 SQL 片段。下面还有两个同级的子标签<when>
,<otherwise>。
<when test = "条件">:满足条件就直接执行里面的SQL语句,然后结束<choose>。
<otherwise>:所有<when>标签里的条件都不满足,就执行这个标签里的SQL语句。
标签使用
<choose>
<when test="condition1">...</when>
<when test="condition2">...</when>
<otherwise>...</otherwise>
</choose>
(4)<set>
标签
用于
UPDATE
语句中,移除多余的逗号。类似于<where>标签的功能。
标签使用
UPDATE table
<set>
...
</set>
WHERE ...
说明:常用于修改操作中,因为不止一个字段,所以,在动态执行的过程中可能出现多逗号或者少逗号的情况,而改标签就自动管理逗号的增加和减少。
(5)<foreach>标签的使用
用于循环,比如生成
IN
子句。主要的属性为
- tiem 表示迭代出每一个元素的别名
- index 指定迭代的索引
- collection 被迭代的集合(类型可以是list、map)
- separator 迭代分隔符,表示每次迭代中间用什么符号分割
- open 和 close 表示以什么符号将集合元素包装起来
<foreach item="item" index="index" collection="list" open="(" separator="," close=")">
#{item}
</foreach>
(6)<sql>标签的使用
定义可重复使用的SQL片段,在字段比较多的情况下及其实用。
标签使用
3. 案例巩固
1.导入员工表
2.编写EmployeeMapper接口
package com.its.mapper;
import com.its.pojo.Employee;
import org.apache.ibatis.annotations.Param;
import java.util.ArrayList;
import java.util.List;
public interface EmployeeMapper {
List<Employee> selectEmployeeList(@Param("name") String name,@Param("position") String position,@Param("entryTime") String entryTime);
List<Employee> selectEmployeeList1(@Param("name")String name, @Param("position")String position);
List<Employee> selectEmployeeList2(@Param("wages") ArrayList<Integer> wages);
}
编写映射文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.its.mapper.EmployeeMapper">
<!--sql片段-->
<sql id="employee">
id,name,position,entryTime,wage,bonus
</sql>
<!--用<include refid="employee"/>该sql片段,就只节代表标签里面的内容-->
<select id="selectEmployeeList" resultType="com.its.pojo.Employee">
select <include refid="employee"/> from employee
<where>
<if test="name!=null and name!=''">
and name like concat('%',#{name},'%')
</if>
<if test="position!=null and position!=''">
and position = #{position}
</if>
<if test="entryTime!=null and entryTime!=''">
and date(entryTime)= #{entryTime}
</if>
</where>
</select>
<select id="selectEmployeeList1" resultType="com.its.pojo.Employee">
select name,wage from employee
<where>
<choose>
<when test="name!=null and name!=''">
name = #{name}
</when>
<when test="position!=null and position!=''">
position = #{position}
</when>
<otherwise>
wage < 10000
</otherwise>
</choose>
</where>
</select>
<select id="selectEmployeeList2" resultType="com.its.pojo.Employee">
select <include refid="employee"/> from employee where wage in
<foreach collection="wages" item="wage" separator="," open="(" close=")">
#{wage}
</foreach>
</select>
</mapper>
在mybatis文件中引入EmployeeMapper.xml映射文件
3.进行功能测试。
测试1:动态的查询员工,可以根据名字查询,职位查询,入职时间查询,或者组合查询。
测试代码
如上图所示,三个参数可以任意填写,SQL语句都可以运行,具体SQL语句分析如下。
测试2:根据字段查询指定的员工,如果没有符合条件的,就将所有员工的工资 < 10000员工信息查询出来出来
测试代码
如上图,如果一个字段都不传递,则会输出工资低于10000的员工信息,具体SQL代码分析如下
测试3:查询工资为15000,12000,8500的人
测试代码
如上图,参数为集合类型,SQL语句需要遍历集合里面的工资信息,只能用foreach标签,具体SQL分析如下
【foreach标签运行流程】
- MyBatis 在执行 SQL 语句之前会先解析
<foreach>
标签的内容。然后将集合或者多值参数绑定到collection属性上。- 如上图所示,对于 wages列表中的每一个元素,item属性中的 wage 值 来引用该元素
<foreach>
标签中的open
和close
属性会被添加到生成的 SQL 语句的开始和结束位置。而separator
属性定义了循环体之间的分隔符,通常是一个逗号。生成的 SQL 语句看起来像这样:SELECT * FROM users WHERE id IN (id1, id2, id3, ...)
- 最后,执行 SQL 语句: