Mybatis--动态SQL

一、定义        

        SQL语句会随着用户的输入或外部条件的变化而变化,我们称为动态SQL。在Mybatis中提供了很多实现动态SQL的标签,我们学习Mybatis中的动态SQL就是掌握这些动态SQL标签。

二、动态SQL标签

(一)if标签

<if>:用于判断条件是否成立。使用test属性进行条件判断,如果条件为true,则拼接SQL。

<if test="条件表达式"> 要拼接的sql语句 </if>

 案例:

        我们的前端页面如下图,在查询框中输入内容作为查询的条件,可以在每个框中输入内容也可在部分框中输入内容。

在XML文件中我们编写sql语句,如下:

<mapper namespace="com.itheima.mapper.EmpMapper">

    <!--查询操作-->
    <select id="getEmpList" resultType="com.itheima.pojo.Emp">
        select * from emp
        where name like concat('%',#{name},'%')
          and gender = #{gender}
          and entrydate between #{start} and #{end}
        order by update_time desc
    </select>

</mapper>

在查询框中我们输入的内容为:张   男   2010-01-01 2020-01-01

这样的输入条件可以得到正确的结果,查询结果如图:

        当我们不把条件填写完整时,我们应该根据输入条件的不同修改查询语句后面的条件,这里就需要用到if标签,test属性里面是条件,如果条件为true,就把if标签包裹的sql语句展示,否则不展示:

<select id="getEmpList" resultType="com.itheima.pojo.Emp">
        select * from emp
        where 
        <if test="name != null">
            name like concat('%',#{name},'%')
        </if>
        <if test="gender != null">
            and gender = #{gender}
        </if>
        <if test="start != null and end != null">
            and entrydate between #{start} and #{end}
        </if>
        order by update_time desc
 </select>

        其实在另一种情况下还会出现问题,对于上面的代码如果只有第二个if中的条件成立,我们的where条件就会变成 where and gender = ?,很显然and是多余的,这里就要使用where标,where只会在子元素有内容的情况下才插入where子句,而且会自动去除子句的开头的and或or:

<select id="getEmpList" resultType="com.itheima.pojo.Emp">
        select * from emp
        <where>
            <if test="name != null">
                name like concat('%',#{name},'%')
            </if>
            <if test="gender != null">
                and gender = #{gender}
            </if>
            <if test="start != null and end != null">
                and entrydate between #{start} and #{end}
            </if>
        </where>
        order by update_time desc
    </select>

(二)set标签

<set>:动态的在SQL语句中插入set关键字,并会删掉额外的逗号。(用于update语句中)

案例:完善更新员工功能,修改为动态更新员工数据信息

  • 动态更新员工信息,如果更新时传递有值,则更新;如果更新时没有传递值,则不更新
  • 解决方案:动态SQL

映射文件中的代码如下: 

<mapper namespace="com.itheima.mapper.EmpMapper">

    <!--更新操作-->
    <update id="update">
        update emp
        <set>
            <if test="username != null">
                username=#{username},
            </if>
            <if test="name != null">
                name=#{name},
            </if>
            <if test="gender != null">
                gender=#{gender},
            </if>
            <if test="image != null">
                image=#{image},
            </if>
            <if test="job != null">
                job=#{job},
            </if>
            <if test="entrydate != null">
                entrydate=#{entrydate},
            </if>
            <if test="deptId != null">
                dept_id=#{deptId},
            </if>
            <if test="updateTime != null">
                update_time=#{updateTime}
            </if>
           </set>
        where id=#{id}
    </update>

</mapper>

        如果不使用set标签,而是直接使用set,遇到的问题就和案例1中直接使用where类似(出现多余的and或or),在这里会出现多余的逗号。

(三)foreach

语法:

<foreach collection="集合名称" item="集合遍历出来的元素/项" separator="每一次遍历使用的分隔符" open="遍历开始前拼接的片段" close="遍历结束后拼接的片段">

</foreach>

案例3:批量删除

 映射文件中的代码:

<mapper namespace="com.itheima.mapper.EmpMapper">
    <!--删除操作-->
    <delete id="deleteByIds">
        delete from emp where id in
        <foreach collection="ids" item="id" separator="," open="(" close=")">
            #{id}
        </foreach>
    </delete>
</mapper> 

(四)sql和include

在书写映射文件时,可能会出现冗余的代码,比如:

         显然上面两个模块的代码的褐色部分是冗余的。在写java代码时为了避免冗余我们会将相同的部分抽出来组成一个方法,在这里也使用类似的思想。我们可以对重复的代码片段进行抽取,将其通过<sql>标签封装到一个SQL片段,然后再通过<include>标签进行引用。

  • <sql>:定义可重用的SQL片段

  • <include>:通过属性refid,指定包含的SQL片段

SQL片段: 抽取重复的代码

<sql id="commonSelect">
 	select id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time from emp
</sql>

然后通过<include> 标签在原来抽取的地方进行引用。操作如下:

<select id="list" resultType="com.itheima.pojo.Emp">
    <include refid="commonSelect"/>
    <where>
        <if test="name != null">
            name like concat('%',#{name},'%')
        </if>
        <if test="gender != null">
            and gender = #{gender}
        </if>
        <if test="begin != null and end != null">
            and entrydate between #{begin} and #{end}
        </if>
    </where>
    order by update_time desc
</select>

三、总结

        if标签,用来决定是否拼接其所包裹的sql,其中test属性即为条件,条件成立则拼接;

        where标签,放置有多余的and或or出现;

        set标签,用与update语句中,放置有多余的逗号出现;

        foreach标签,当所传的参数为集合时,用来遍历集合,其中属性collection用来说明集合的名称,item用来说明集合遍历出来的元素/项,seperator说明每一次遍历使用的分隔符,open指遍历开始前输出的内容,close指遍历结束后输出的内容;

        sql用来抽取sql语句相同的部分,可以指定一个id属性值便于后续引入;

        include用来引入被抽出的sql语句,通过id值来指定被引入的sql。

        

  • 14
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Mybatis-plus是在Mybatis基础上进行封装的一个框架,它简化了平时开发过程中对常用接口的调用,可以省去一些繁琐的操作。然而,对于一些更为复杂的查询,Mybatis-plus可能无法满足需求,此时就需要我们自定义SQL语句来实现。通过在入口类的MybatisSqlSessionFactoryBuilder#build方法中注入mybatis-plus自定义的动态配置xml文件,可以实现自定义SQL语句和动态SQL的功能。具体的实现步骤如下: 1. 在应用启动时,在入口类的MybatisSqlSessionFactoryBuilder#build方法中将mybatis-plus的自定义动态配置xml文件注入到Mybatis中。 2. 在自定义的动态配置xml文件中,可以使用各种Mybatis-plus提供的方法来实现动态SQL的功能,比如IF标签、CHOOSE标签、FOREACH标签等。 3. 在自定义SQL语句中,可以结合Mybatis-plus的Wrapper类来实现条件查询,例如使用LambdaQueryWrapper来构建查询条件。 总结起来,Mybatis-plus提供了简化开发的接口,但对于一些更为复杂的查询,仍然需要我们自定义SQL语句和动态SQL来实现。通过注入自定义的动态配置xml文件,并结合Mybatis-plus提供的方法和Wrapper类,可以实现更加灵活和高效的数据查询。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [mybatis-plus/mybatis 自定义 sql 语句、动态 sql](https://blog.csdn.net/CREATE_17/article/details/109117091)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [Mybatis Plus实现动态SQL语句的原理,你知道吗?](https://blog.csdn.net/weixin_38405253/article/details/119880820)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值