MyBatis 之六:动态 SQL 案例详解

本文介绍了MyBatis框架中的动态SQL特性,包括if、set、where、trim、choose和foreach等标签的使用,展示了如何在XML映射文件中根据运行时参数动态构建和执行SQL,以及如何处理数组、List和Set等不同类型的参数传递,以提高代码复用和防止SQL注入。
摘要由CSDN通过智能技术生成

(关注+点赞是我继续的最大动力,谢谢支持!)

动态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);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zp8126

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值