(关注+点赞是我继续的最大动力,谢谢支持!)
动态SQL
MyBatis 动态SQL是MyBatis框架提供的一种强大功能,它允许在XML映射文件中编写可灵活变化的SQL语句,这些SQL语句能够根据运行时传入参数的条件动态地生成和执行。这极大地提高了代码的复用性和SQL查询的灵活性,并且降低了手动拼接SQL字符串带来的错误风险
常用动态SQL标签:
if
set
where
trim
choose(when、otherwise)
foreach
if 和 set
set 用于 update 标记中,动态判断主体中是否包含多余的逗号“,”,多余的自动删除
<update id="updatexxxxxx" parameterType="emp">
update emp
<set>
<if test="salary!=null">
sal=#{salary},
</if>
<if test="deptno!=null">
deptno=#{deptno},
</if>
<if test="ename!=null">
ename=#{ename},
</if>
<if test="hiredate!=null">
hiredate=#{hiredate},
</if>
</set>
where empno=#{empno}
</update>
where
where 用于条件查询拼接,动态添加where 关键字并并判断是否有多余 and ,有的话直接截取掉
注意:在SQL 中如果包含了特殊的字符时,需要使用 CDATA 来处理
<![CDATA[ and sal <= #{maxSalary} ]]>
<!--通过部门编号查询下面的所有员工-->
<select id="queryAllxxxxxx" resultType="empdto">
select empno,ename,sal,hiredate,deptno,gender from emp
<where>
<if test="ename!=null">
and ename=#{ename}
</if>
<if test="minSalary!=null">
<![CDATA[
and sal>=#{minSalary}
]]>
</if>
<if test="maxSalary!=null">
<![CDATA[
and sal <= #{maxSalary}
]]>
</if>
<if test="deptno!=null">
and deptno=#{deptno}
</if>
</where>
</select>
choose(when--otherwise)
choose 类似于 switch 语句,每次只能拼接单个语句成立
- 注意下面 <bind>用法:
声明临时变量,接收表达式的结果,以便后面使用
<select id="selectByCondition" resultType="emp">
select empno,ename,sal,hiredate,deptno,gender from emp
<where>
<choose>
<when test="empno!=null">
empno=#{empno}
</when>
<when test="ename!=null">
<!--String _ename="%"+ename+"%";-->
<bind name="_ename" value="'%'+ename+'%'"/>
ename like #{_ename}
</when>
<otherwise>
deptno = #{deptno}
</otherwise>
</choose>
</where>
</select>
trim
trim 可以灵活完成不同字符串的截取和拼接,可以替代 set 或 where
set 只能处理逗号的替换截取,where 只能处理 and
trim 则可以处理任意的字符截取和拼接
替换 set 用法:
suffixOverrides="," :表示后缀覆盖:在主体内容拼接完成后,如果最后多出逗号,则覆盖掉
prefix="set " :前缀,在拼接完成后,前面补充拼接上指定的前缀 set ,注意后面带上空格
<!--trim-->
<update id="update" parameterType="emp">
update emp
<trim prefix="set " suffixOverrides=",">
<if test="salary!=null">
sal=#{salary},
</if>
<if test="deptno!=null">
deptno=#{deptno},
</if>
<if test="ename!=null">
ename=#{ename},
</if>
<if test="hiredate!=null">
hiredate=#{hiredate},
</if>
</trim>
where empno=#{empno}
</update>
替换 where 用法
<select id="queryAll" resultType="empdto">
select empno,ename,sal,hiredate,deptno,gender from emp
<trim prefix=" WheRe " prefixOverrides="and" >
<if test="ename!=null">
and ename=#{ename}
</if>
<if test="minSalary!=null">
<![CDATA[
and sal>=#{minSalary}
]]>
</if>
<if test="maxSalary!=null">
<![CDATA[
and sal <= #{maxSalary}
]]>
</if>
<if test="deptno!=null">
and deptno=#{deptno}
</if>
</trim>
</select>
foreach
接收集合或数组时,循环拼接SQL
注意传参的多种情况:
void deleteMany(Integer... id); void deleteByList(List<Integer>id); void deleteBySet(Set<Integer> id);
传参为 数组、List、Set 时,在映射文件中的属性取值有所不同
传参为数组时:
<!--empno in (2,3,4)
for(String s:list){}
在传参为数组的情况下:
错误提示: Available parameters are [array, arg0]
有效的参数应该是 array 或 arg0
-->
<delete id="deleteMany">
delete from emp
<where>
<foreach collection="arg0" open="empno in(" close=")" separator="," item="sid">
#{sid}
</foreach>
</where>
</delete>
传参为列表 List 时:
<!--传参为 list 的情况:
Parameter 'xxxx' not found. Available parameters are [arg0, collection, list]
-->
<delete id="deleteByList">
delete from emp
<where>
<foreach collection="list" open="empno in(" close=")" separator="," item="sid">
#{sid}
</foreach>
</where>
</delete>
传参为集合 Set 时:
<!--set 类型参数:【arg0,collection】-->
<delete id="deleteBySet">
delete from emp
<where>
<foreach collection="collection" open="empno in(" close=")" separator="," item="sid">
#{sid}
</foreach>
</where>
</delete>
$ 和#
在映射文件中引用传参时,可以同时使用#{} 或 ${}
例如:实现员工的多条件查询,根据员工部门编号和姓名来做查询
修改映射文件,新增下面代码:
<!--根据用户名和部门编号 多条件查询-->
<select id="queryEmp" resultType="emp">
select empno,ename,sal salary,hiredate
from emp
where deptno=${dno} and ename='${ename}'
</select>
注意:上面的 ${ename} 必须带单引号的
上面配置使用了 ${} 生成的 SQL 如下:
==> Preparing: select empno,ename,sal salary,hiredate from emp where deptno=30 and ename='小明' ==> Parameters: <== Total: 0
${} 用来拼接 SQL 语句的,使用时注意对于字符型,手动添加单引号。不安全,可能引起SQL注入安全问题
#{} 先生成带占位符 ? 的语句,再给占位符赋值,好处,类型处理自动判断识别,灵活和安全
再注意:
如果传入多个参数,除了可以使用实体类之外,还可以使用 Map 来传参
public static void main(String[] args) {
SqlSession session = MyBatisUtil.getSqlSession();
Map<String,Object> param = new HashMap<>();
param.put("dno",30);
param.put("ename","小明");
List<Emp> list = session.selectList("queryEmp", param);
list.forEach(System.out::println);
}