zoukankan      html  css  js  c++  java
  • Mybatis动态SQL

    一:动态SQL语句

    动态SQL可以说是Mybatis的一大特点。在使用过JDBC来写SQL语句,你应该能理解不同的条件有不同的SQL语句要拼接,往往一个字符串被东拼西凑,特别痛苦,而且还得保证拼接的时候2段SQL片段之间要保留空格等待,利用动态SQL可以保证彻底摆脱这种痛苦!

      其实使用动态SQL也不是一件容易的事,但借助可用于任何 SQL 映射语句中的强大的动态 SQL 语言,MyBatis 显著地提升了这一特性的易用性。

      如果有之前在学web的时候接触过JSTL或者任何基于类XML语言的文本处理器,,或许你对动态SQL有一定的似曾相识感觉,在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。

      Mybatis中用于实现动态SQL元素主要有if、choose、trim、where、set、foreach

    这里我们快速准备一下简单的小框架吧!

    1:if标签

    动态 SQL 通常要做的事情是有条件地包含 where 子句的一部分。简单说传来的值用if判断,有的话就拼接到where后面。

        <!--根据性别和年龄查询-->
        <!--注意:必须要带一个where 1=1 否则sql语句少了where语句,,if判断某个值为空就不会拼接某个片段 -->
        <select id="findByAgeAndSex" parameterType="student" resultMap="studentMapper">
            select * from student where 1=1
            <if test="age!=0">
                and sage=#{age}
            </if>
            <if test="sex!=null and sex!=''">
                and ssex=#{sex}
            </if>
        </select>

    2:choose、when、otherwise标签

    这3个标签是一个整体和JSTL的一样,它们的本质都有点像java的switch分支语句,还是按照上面的例子,假设我传来年龄就按照年龄查询,传来性别就按照性别查询,年龄和性别都传来,就按照标签判断的先后顺序选择一个靠前的,然后下一个判断将不在执行,直接跳出,如果都不传则执行otherwise标签

    <!--根据性别和年龄的其中一个查询-->
        <select id="findByAgeAndSexChoose" parameterType="student" resultMap="studentMapper">
            <!--基本sql语句-->
            select * from student where 1=1
            <!--switch开始-->
            <choose>
                <!--case :-->
                <when test="age!=0">
                    and sage=#{age}
                </when>
                <!--case :-->
                <when test="sex!=null and sex!=''">
                    and ssex=#{sex}
                </when>
                <!--default 如果都不成立则执行下面查询5条数据-->
                <otherwise>
                    limit 5
                </otherwise>
            </choose>
        </select>

    3:where、set、trim标签

    先说一下where,其实大家有没有发现,我前2个示例都有where 1=1,这是干嘛用的呢?其实这个是一个恒等式,加where 1=1和不加都一样,但是加上了,后面的拼接语句就可以使用 and xx=xx and xxx=xxx 如果没加,那么后面的if判断成立就会形成一个select * from student  where and sage=xx;大家肯定发现错误了,其实Mybatis帮我们解决了where 1=1的拼接问题,我们可以不用自己手动写where属性了,我就改造一下第一个例子

    <!--根据性别和年龄查询-->
        <!--加上where标签后就不用写恒等式了,就连前面的and也可写可不写 看下面的2个if里面-->
        <select id="findByAgeAndSex" parameterType="student" resultMap="studentMapper">
            select * from student
            <where>
                <if test="age!=0">
                     sage=#{age}
                </if>
                <if test="sex!=null and sex!=''">
                    and ssex=#{sex}
                </if>
            </where>
        </select>

    现在我们来聊聊trim,这个东西第一眼看上去特别难理解,以至于我都不知道是啥玩意,但是明白以后还是感觉不错的,就是用的很少,先不废话直接上代码看看

    <!--
        使用trim标签完成where案例
        trim标签有4个属性:
        prefix:前缀覆盖并增加其内容。也就是给中的sql语句加上前缀;
        suffix:后缀覆盖并增加其内容。给包裹的sql语句加上后缀;
        prefixOverrides:前缀判断的条件。取消指定的前缀,如where;
        suffixOverrides:后缀判断的条件。取消指定的后缀,如"and |or "逗号等。
        -->
        <select id="findByAgeAndSex" parameterType="student" resultMap="studentMapper">
            select * from student
            <trim prefix="where" prefixOverrides="or |and ">
                <if test="age!=0">
                    and sage=#{age}
                </if>
                <if test="sex!=null">
                    and ssex=#{sex}
                </if>
            </trim>
        </select>
        <!--
            prefix代表前缀,它包裹着2个if标签,假设2个if都成立则语句是这样的
            select * from student where and sage=#{age} and ssex=#{sex};
            这样的语句是不是有问题呢?仔细一看 where后面有个and,没错因为if判断成功,
            就会拼接一个sql片段 and 也被拼接上了,但是别着急
            prefixOverrides上场,这个代表前缀重写,prefixOverrides="and |or ",凡是前缀为
            and或者or的全部重写,那重新成什么呢?别多想 说白了就是把匹配上的前缀删除了
            所以我们再总结一下 :
            select * from student SQL语句
            prefix="where" 开始添加前缀
            where and sage=#{age} and ssex=#{sex}
            prefixOverrides="and |or "开始前缀重写 就是去除where后全部语句最前面匹配重写
            where sage=#{age} and ssex=#{sex}
            相对于的后缀和后缀重写也是一样的,只不过在后面
            
            注意:"and▢|or▢"必须要有空格 否则匹配不上
        -->

    聊完trim我们就来解决最后一个set了,这个玩意比trim容易,虽然trim难点,但是它可以写出set和where的功能,现在我来介绍一下set

    <!--更新学生姓名  地址-->
        <!--这个set标签的内部可以放更新的字段 可以自动去除尾部的逗号,-->
        <update id="update" parameterType="student">
            update student
            <set>
                 <if test="name!=null and name!=''">sname=#{name},</if>
                 <if test="address!=null and address!=''">saddress=#{address},</if>
            </set>
            where sid=#{id}
        </update>
        <!--
            其实trim也可以完成对上面的操作
             update student
            <trim prefix="set" suffixOverides=",">
                 <if test="name!=null and name!=''">sname=#{name},</if>
                 <if test="address!=null and address!=''">saddress=#{address},</if>
            </trim>
            where sid=#{id}
        -->

    4:foreach标签

      动态SQL的另一种常见的使用场景就是对集合进行遍历(尤其是遍历in条件语句的内部),在这我来给大家介绍一个mybatis的foreach循环集合标签,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及集合项迭代之间的分隔符。这个元素也不会错误地添加多余的分隔符,你可以将任何可迭代对象(如 List、Set 等)、Map 对象或者数组对象作为集合参数传递给 foreach。当使用可迭代对象或者数组时,index 是当前迭代的序号,item 的值是本次迭代获取到的元素。当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值。

    <!--查询包含的id-->
        <!--
            open:整个循环内容开头的字符串。
            close:整个循环内容结尾的字符串。
            separator:每次循环的分隔符。
            item:从迭代对象中取出的每一个值。
            index:如果参数为集合或者数组,该值为当前索引值,如果参数为Map类型时,该值为Map的key。
            collection:要迭代循环的属性名。
               List<Student> findContionId(List<Integer> ids);这个是我接口的名称
               大家好奇为什么collection值是list而不上ids呢?在这里就有明确的答案引用自别处博客-->
        <select id="findContionId" parameterType="Integer" resultMap="studentMapper">
            select * from student
            <where>
                <foreach collection="list" item="x" open="sid in (" close=")" separator=",">
                    #{x}
                </foreach>
            </where>
        </select>

    5:SQL片段

    虽然SQL片段不属于动态SQL里面的,但是我认为和动态SQL这一章节将比较合适,那什么是SQL片段呢?大家肯定用过<jsp:include="xx" />这个动作元素吧,其实SQL片段和这个差不多,都是把一个SQL片段封装起来,后期谁用谁调用这个片段就行了

    <!--SQL片段定义-->
        <sql id="sqlid">
            select * from student
        </sql>
        <!--查询单个-->
        <select id="findById" resultMap="studentMapper">
            <!--调用SQL片段 通过id-->
            <include refid="sqlid"></include>
             where sid=#{id}
        </select>

    结语:今天带大家了解了一下mybatis的动态sql,在接下来的一篇文章来为大家介绍一下mybatis的多表操作,和后期的注解开发希望大家多多支持,希望我那文章对你有一点点帮助,如有意见或者不同观点,希望您可以通过评论或者私信交流谢谢

  • 相关阅读:
    (八)DVWA之SQL Injection--SQLMap&Burp测试(Medium)
    (五)SQLMap工具检测SQL注入漏洞、获取数据库中的数据
    (四)SQLMap之Tamper篡改脚本的类型、作用、适用场景
    (七)DVWA之SQL Injection--SQLMap测试(Low)
    (三)SQLMap工具-使用选项的操作命令&功能
    20190923-13Linux企业真实面试题 000 021
    20190923-12Linux软件包管理 000 020
    20190923-11Linux crond 系统定时任务 000 019
    20190923-10Linux进程线程类 000 018
    20190923-09Linux磁盘分区类 000 017
  • 原文地址:https://www.cnblogs.com/antLaddie/p/12779000.html
Copyright © 2011-2022 走看看