【MyBatis】第七篇:动态sql

news2024/11/26 8:58:00

mybatis中的动态sql,其实就是在mybatis中映射配置文件中通过if等判断语句写sql。现在聊一下,常用的的判断语句。

前面准备:

CREATE TABLE `student` (
  `sid` int DEFAULT NULL,
  `sname` varchar(10) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL,
  `sage` int DEFAULT NULL,
  `ssex` varchar(2) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL,
  `gid` int DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;

 
insert  into `student`(`sid`,`sname`,`sage`,`ssex`,`gid`) values 

(1,'张三',18,'男',2),

(2,'赛貂蝉',14,'女',1),

(3,'胡铁花',23,'男',2),

(4,'白飞飞',16,'女',1),

(5,'李寻欢',16,'男',1),

(4,'宫崎',18,'男',2);



if

if标签是通过test数据的表达式进行判断,如果true就执行其标签中的内容,如果false则向反。

常用场景如下,比如在很多伤害数据库中的字段的条件为NULL的时候会影响结果。保留web项目中,前端传递的参数又三个条件,但是三个条件不一定都会被用户选择。然后生成不同的sql从数据库中取出数据。

当然也可以通过如果通过java代码进行判断,然后也可以解决这个问题,不过mybatis的通过xml配置sql语句,所以可能会更直观方便一些。

映射文件:

 <select id="getStudent" resultType="Student">
          <!--   为什么会写 1=1 因为比如例子中sql的条件会通过and 连接 防止出现问题采用这个方法 -->
          SELECT  sid ,  sname ,  sage ,  ssex ,  gid  FROM  testmybatis.student WHERE 1=1
          <if test="sid!='' and sid !=null">
              and sid=#{sid}
          </if>
          <if test="sname!='' and sname !=null">
              and sname=#{sname}
          </if>
          <if test="sage!='' and sage !=null">
              and sage=#{sage}
          </if>
          <if test="ssex!='' and ssex !=null">
              and ssex=#{ssex}
          </if>
          <if test="gid!='' and gid !=null">
              and gid=#{gid}
          </if>
      </select>

映射接口类中的方法:

    List<Student>  getStudent(Student student);

调用方法:

  Student student=new Student(null,null,null,"女",null);
        System.out.println("  --------------------       " +  studentMapper.getStudent(student) );

在这里插入图片描述

注意:

  • if中的test属性表达式中,直接用对象的属性进行判断,不需要通过#{}或者${}.
  • 一般因为有连接关键字,所以在where后面会通过一个伪条件而实现动态代码。

where标签

当然如果不想在where中天津一个伪条件的话,还可以通过where标签进行实现,具体如下:

 <select id="getStudent" resultType="Student">
          <!--   为什么会写 1=1 因为比如例子中sql的条件会通过and 连接 防止出现问题采用这个方法 -->
          SELECT  sid ,  sname ,  sage ,  ssex ,  gid  FROM  testmybatis.student
              <where>
                  <if test="sid!='' and sid !=null">
                      sid=#{sid}
                  </if>
                  <if test="sname!='' and sname !=null">
                      and sname=#{sname}
                  </if>
                  <if test="sage!='' and sage !=null">
                      and sage=#{sage}
                  </if>
                  <if test="ssex!='' and ssex !=null">
                      and ssex=#{ssex}
                  </if>
                  <if test="gid!='' and gid !=null">
                      and gid=#{gid}
                  </if>
              </where>

      </select>

然后看一下结果,现在换成性别为男:

在这里插入图片描述

也是没有问题,这个时候可以看出where标签有两个作用:

  • 第一:sql语句需要些where 关键字,where标签会自动添加这个关键字。
  • 第二:如果第一个条件不成立,而导致where后面and关键字的话,where标签会自动将首个and优化掉,让sql符合要求。而这种取消,只是取消条件的前面and。

如果这样写呢?把and放在后面。

<select id="getStudent" resultType="Student">
        <!--   为什么会写 1=1 因为比如例子中sql的条件会通过and 连接 防止出现问题采用这个方法 -->
        SELECT sid , sname , sage , ssex , gid FROM testmybatis.student
        <where>
            <if test="sid!='' and sid !=null">
                sid=#{sid} and
            </if>
            <if test="sname!='' and sname !=null">
                sname=#{sname} and
            </if>
            <if test="sage!='' and sage !=null">
                sage=#{sage} and
            </if>
            <if test="ssex!='' and ssex !=null">
                ssex=#{ssex} and
            </if>
            <if test="gid!='' and gid !=null">
                gid=#{gid}
            </if>
        </where>

    </select>

在这里插入图片描述

直接保存了,而这个时候需要使用另一个标签trim。

trim

先看一下trim标签:

在这里插入图片描述

可以看出trim标签有四个属性。具体有什么用呢?

属性描述
prefix在tirm标中的内容前添加指定内容
prefixOverrides在tirm标中的内容后添加指定内容
suffix在tirm标中的内容前面删除指定内容
suffixOverrides在tirm标中的内容后面删除指定内容

看着有些绕,还是老规矩用代码演示:

 <select id="getStudent" resultType="Student">
        <!--   为什么会写 1=1 因为比如例子中sql的条件会通过and 连接 防止出现问题采用这个方法 -->
        SELECT sid , sname , sage , ssex , gid FROM testmybatis.student
        <trim prefix="where" suffixOverrides="and">
            <if test="sid!='' and sid !=null">
                sid=#{sid} and
            </if>
            <if test="sname!='' and sname !=null">
                sname=#{sname} and
            </if>
            <if test="sage!='' and sage !=null">
                sage=#{sage} and
            </if>
            <if test="ssex!='' and ssex !=null">
                ssex=#{ssex} and
            </if>
            <if test="gid!='' and gid !=null">
                gid=#{gid}
            </if>
        </trim>

    </select>

看一下结果:

在这里插入图片描述

解读

<trim prefix="where" suffixOverrides="and">

因为trim标签不会主动添加where ,所以需要通过prefix在条件语句前面添加where。因为and是写在后面的,如果最后出现and会影响sql语句,所以通过设置suffixOverrides来将最后面的and删除,如果没有也就不必删除了

choose —when—otherwise

这个语句判断记住一点其更像是是java中switch–case—default。

意思就是所有的条件,只要最上面的满足后面的就直接跳出。

<select id="getStudent" resultType="Student">
        <!--   为什么会写 1=1 因为比如例子中sql的条件会通过and 连接 防止出现问题采用这个方法 -->
        SELECT sid , sname , sage , ssex , gid FROM testmybatis.student
        <where >

    <choose>
        <when test="sid!='' and sid !=null">
            <!-- 因为只会判断一个条件满足,所以不需要添加and这样的连接符 -->
            sid=#{sid}
        </when>
        <when test="sname!='' and sname !=null">
            sname=#{sname}
        </when>
        <when test="sage!='' and sage !=null">
            sage=#{sage}
        </when>
        <when test="ssex!='' and ssex !=null">
            ssex=#{ssex}
        </when>
        <otherwise>
            gid=#{gid}
        </otherwise>
    </choose>

</where>
</select>

然后调用方法:

  Student student=new Student(null,null,14,"男",null);
        System.out.println("  --------------------       " +  studentMapper.getStudent(student) );

然后看一下结果:

在这里插入图片描述

这里注意数据库中没有男性14岁的学生,而且性别为男的条件也没有其效果,所以说只会选择一个条件。

注意:choose中的必须有一个when标签,而otherwise标签最多只有一个

foreach

这个标签看见就知道是一个循环语句,具体是如何用呢?看实例吧。

foreach 元素的属性主要有 item,index,collection,open,separator,close。

属性描述
item表示集合中没一个元素的迭代的名字,这个在jsp中也有。毕竟这个元素有可能是一个对象,方便取出属性值。
index指定一个名字,用户表示在迭代过程中,每次迭代到的位置,可以理解为for(int i=0;i++;i<5)中的i。可以为起一个名字。
open表示该语句什么时候开始
separator表述迭代数据中间用什么内容作为分隔符。
close表示什么时候结束

还是老规矩,用代码演示:

先创建一个list,然后用来插入演示:

 List<Student> list=new ArrayList<Student>();
        list.add(new Student(null,"v胖",3,"男",3));
        list.add(new Student(null,"奎爷",33,"男",1));
        list.add(new Student(null,"娜美",15,"女",3));
        studentMapper.insertListStudent(list);
  <insert id="insertListStudent">
       INSERT INTO  testmybatis.student ( sid ,  sname ,  sage ,  ssex ,  gid ) VALUES
       <foreach collection="studentList" item="student"   separator="," >
             <!--sql插入数应该有一对() 不可以使用 open和close会在前后放内容,包裹整个数据,比如应该是(student),(student),(student) 却变成(student,student,student)-->
          ( #{student.sid}, #{student.sname}, #{student.sage}, #{student.ssex}, #{student.gid})
       </foreach>
                                                                      
   </insert>

接口类的方法:

 void insertListStudent(@Param("studentList") List<Student> studentList);

运行结果:

在这里插入图片描述

现在来一个批量删除的操作,这个可以使用多个属性如下操作:

   void deleteArr(@Param("arr") int[]  arr);
 <delete id="deleteArr">
      delete from student where sid in
        <foreach collection="arr" separator="," open="(" close=")" item="sid">
            #{sid}
        </foreach>
    </delete>

然后调用方法:

        int[] arr={12,13,14};
        studentMapper.deleteArr(arr);

现在看一下结果:

在这里插入图片描述

所以可以看在foreach中的open和close的具体效果。

sql

还有一个sql标签,这个标签可以记录一段sql,在需要使用的适合用incluede标签进行引用。

还是老规矩,进程代码演示,用上面的例子进行演示:

先不用sql的如下:

<select id="getStudent" resultType="Student">
        <!--   为什么会写 1=1 因为比如例子中sql的条件会通过and 连接 防止出现问题采用这个方法 -->
        SELECT sid , sname , sage , ssex , gid FROM testmybatis.student
        <where >

    <choose>
        <when test="sid!='' and sid !=null">
            <!-- 因为只会判断一个条件满足,所以不需要添加and这样的连接符 -->
            sid=#{sid}
        </when>
        <when test="sname!='' and sname !=null">
            sname=#{sname}
        </when>
        <when test="sage!='' and sage !=null">
            sage=#{sage}
        </when>
        <when test="ssex!='' and ssex !=null">
            ssex=#{ssex}
        </when>
        <otherwise>
            gid=#{gid}
        </otherwise>
    </choose>

</where>
</select>

然后是使用sql标签的:

<select id="getStudent" resultType="Student">
        <!--   为什么会写 1=1 因为比如例子中sql的条件会通过and 连接 防止出现问题采用这个方法 -->
        SELECT <include refid="studentColumns"></include> FROM testmybatis.student
        <where>

            <choose>
                <when test="sid!='' and sid !=null">
                    <!-- 因为只会判断一个条件满足,所以不需要添加and这样的连接符 -->
                    sid=#{sid}
                </when>
                <when test="sname!='' and sname !=null">
                    sname=#{sname}
                </when>
                <when test="sage!='' and sage !=null">
                    sage=#{sage}
                </when>
                <when test="ssex!='' and ssex !=null">
                    ssex=#{ssex}
                </when>
                <otherwise>
                    gid=#{gid}
                </otherwise>
            </choose>

        </where>

这样方便将一些常用的sql公用部分拆出来,然后进行使用,有点像是java中的公共方法提出的感觉,这样方便使用。

script

这个标签是搭配着注解使用的,还是老规矩进行代码演示:

  @Delete(" <script>" +
            "delete from student where sid in " +
            "<foreach collection=\"arr\" separator=\",\" open=\"(\" close=\")\" item=\"sid\"> " +
            " #{sid} " +
            "  </foreach>" +
            " </script>")
    
    void deleteArr(@Param("arr") int[]  arr);

可以看出通过script标签可以将本来在xml中写的配置信息,通过注解写在java文件中,虽然方便但是说实话没有通过xml看着配置信息清晰。

bind 标签

元素允许你在 OGNL 表达式以外创建一个变量,并将其绑定到当前的上下文。

然后简单演示:

  <select id="selectStudentLike" resultType="Student">
        <bind name="pattern" value="'%' + name + '%'" />
        SELECT * FROM student
        WHERE sname LIKE #{pattern}
    </select>
    List<Student>  selectStudentLike(  Map<String, String> params);
   Map<String, String> params =new HashMap();
        params.put("name", "三");
        List<Student> studentList = studentMapper.selectStudentLike(params);
        System.out.println(studentList);

看一下结果:

在这里插入图片描述

不过出发在一个sql中使用了多次某个片段,不然不如直接写的方便。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/336400.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2023年深圳/东莞/惠州CPDA数据分析师认证报名入口

CPDA数据分析师认证是中国大数据领域有一定权威度的中高端人才认证&#xff0c;它不仅是中国较早大数据专业技术人才认证、更是中国大数据时代先行者&#xff0c;具有广泛的社会认知度和权威性。 无论是地方政府引进人才、公务员报考、各大企业选聘人才&#xff0c;还是招投标加…

计算机网络-传输层

文章目录前言概述用户数据报协议 UDP(User Datagram Protocol)传输控制协议 TCP(Transmission Control Protocol)TCP 的流量控制拥塞控制方法TCP 的运输连接管理TCP 的有限状态机总结前言 本博客仅做学习笔记&#xff0c;如有侵权&#xff0c;联系后即刻更改 科普&#xff1a…

LeetCode经典问题总结笔记—一文搞懂滑动窗口和哈希表结合使用之3. 无重复字符的最长子串问题(第一篇)

今日主要总结一下可以使用滑动窗口和哈希表结合使用解决的一道题目&#xff0c;3. 无重复字符的最长子串 题目&#xff1a;3. 无重复字符的最长子串 Leetcode题目地址 题目描述&#xff1a; 给定一个字符串 s &#xff0c;请你找出其中不含有重复字符的 最长子串 的长度。 示…

华尔街分析师:斗鱼2023财年前景暗淡,但盈利能力有望提升

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 华尔街预计斗鱼2023财年收入前景悲观 根据S&P Capital IQ的一致性数据&#xff0c;华尔街卖方分析师预计&#xff0c;斗鱼&#xff08;DOYU&#xff09;的收入将从2022财年的71.93亿元下降到2023财年的67.53亿元&#x…

react -- Context

使用Context简单传参例子 解决父子组件多层嵌套传参&#xff0c;中间不用通过props传值 import React, { useContext } from "react"; // 参数对象 const param { title: "星期四" }; // 创建一个 Context 对象 // const MyContext React.createContex…

基于matlab使用机器学习和深度学习进行雷达目标分类

一、前言此示例展示了如何使用机器学习和深度学习方法对雷达回波进行分类。机器学习方法使用小波散射特征提取与支持向量机相结合。此外&#xff0c;还说明了两种深度学习方法&#xff1a;使用SqueezeNet的迁移学习和长短期记忆&#xff08;LSTM&#xff09;递归神经网络。请注…

【快排与归并排序算法】

作者&#xff1a;指针不指南吗 专栏&#xff1a;算法篇 &#x1f43e;或许会很慢&#xff0c;但是不可以停下&#x1f43e; 文章目录一、快速排序 ( Quick Sort )二、归并排序 ( Merge Sort )总结一、快速排序 ( Quick Sort ) 1.思路 找出一个分界点&#xff0c;随机的调整区间…

openmmlab 语义分割算法基础

本文是openmmlab AI实战营的第六次课程的笔记&#xff0c;以下是我比较关注的部分。简要介绍语义分割&#xff1a;如下图&#xff0c;左边原图&#xff0c;右边语义分割图&#xff0c;对每个像数进行分类应用语义分割在个各种场景下都非常重要&#xff0c;特别是在自动驾驶和医…

【docker知识】联合文件系统(unionFS)原理

一、说明 Docker CLI 操作起来比较简单——您只需掌握Create、Run、InspPull和Push容器和图像&#xff0c;但是谁想过Docker 背后的内部机制是如何工作的&#xff1f;在这个简单的表象背后隐藏着许多很酷的技术&#xff0c; UnionFS&#xff08;统一文件系统&#xff09;就是其…

为什么静默安装未经过数字签名的驱动是不可行的?

我想&#xff0c;在 Windows XP 系统上&#xff0c;造成蓝屏的最主要原因是带有 Bug 的设备驱动程序。 请问在座的&#xff0c;谁赞成&#xff0c;谁反对。 因为驱动运行在内核模式&#xff0c;再也没有更高级别的组件对其进行行为监管&#xff0c;它可以做它想做的任何事情。…

Power BI 筛选器函数---Index实例详解

一、Index函数 语法&#xff1a; INDEX ( <检索行号>, [<关系>], [<OrderBy>],[空白],[PartitionBy] ) 含义&#xff1a; 对指定分区(PartitioinBy)中的行&#xff08;关系表&#xff09;&#xff0c;按指定的列进行排序(OrderBy)后&#xff0c;根据&…

医院智能化解决方案-门(急)诊、医技、智能化项目解决方案

【版权声明】本资料来源网络&#xff0c;知识分享&#xff0c;仅供个人学习&#xff0c;请勿商用。【侵删致歉】如有侵权请联系小编&#xff0c;将在收到信息后第一时间删除&#xff01;完整资料领取见文末&#xff0c;部分资料内容&#xff1a;篇幅有限&#xff0c;无法完全展…

Docker镜像的创建

Docker镜像Docker镜像Docker 镜像是一个特殊的文件系统提供容器运行时所需的程序、库、资源、配置等文件包含一些为运行时准备的一些配置参数&#xff08;如匿名卷、环境变量、用户等&#xff09;镜像不包含任何动态数据&#xff0c;其内容在构建之后也不会被改变。Docker镜像的…

论文中常用的注意力模块合集(上)

在深度卷积神经网络中&#xff0c;通过构建一系列的卷积层、非线性层和下采样层使得网络能够从全局感受野上提取图像特征来描述图像&#xff0c;但归根结底只是建模了图像的空间特征信息而没有建模通道之间的特征信息&#xff0c;整个特征图的各区域均被平等对待。在一些复杂度…

【化学试剂】endo-BCN-PEG4-Pomalidomide,(1R,8S,9S)-双环[6.1.0]壬-四聚乙二醇-泊马度胺纯度95%+

一、基础产品数据&#xff08;Basic Product Data&#xff09;&#xff1a;CAS号&#xff1a;N/A中文名&#xff1a;(1R,8S,9S)-双环[6.1.0]壬-四聚乙二醇-泊马度胺英文名&#xff1a;endo-BCN-PEG4-Pomalidomide二、详细产品数据&#xff08;Detailed Product Data&#xff09…

【软件测试】软件测试工作上95%会遇到的问题,你遇到多少?

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 1、测试负责人要进行…

C语言rand和srand用法详解

在实际编程中&#xff0c;我们经常需要生成随机数&#xff0c;例如&#xff0c;贪吃蛇游戏中在随机的位置出现食物&#xff0c;扑克牌游戏中随机发牌。在C语言中&#xff0c;我们一般使用 <stdlib.h> 头文件中的 rand() 函数来生成随机数&#xff0c;它的用法为&#xff…

Redis的事务和锁以及在SpringBoot中的使用

文章目录1、事务2、监视锁3、分布式锁1、事务 Redis中事务的操作主要有三个&#xff1a; # 1、开启事务 # 定事务的开启位置&#xff0c;此指令执行后&#xff0c;后续的所有指令均加入到事务中 1、multi # 2、执行事务 # 设定事务的结束位置&#xff0c;同时执行事务。与mul…

【java】map集合遍历: entrySet()、单独遍历key或者value、 keySet()、iterator遍历

目录 1.增强for循环。利用Map 的 entrySet&#xff08;&#xff09;方法获取元素2.增强for循环。单独遍历key或者value3.增强for循环。利用Map 的 keySet() 方法获取元素4.使用iterator遍历文中实体的定义在上篇笔记中&#xff1a;https://blog.csdn.net/qq_43622777/article/d…

spring面试题 一

一、为了降低Java开发的复杂性&#xff0c;Spring采取了那4种关键策略 基于POJO的轻量级和最小侵入性编程&#xff1b; 通过依赖注入和面向接口实现松耦合&#xff1b; 基于切面和惯例进行声明式编程&#xff1b; 通过切面和模板减少样板式代码。 二、Spring框架的核心&am…