JavaWeb开发 —— MyBatis动态SQL

news2024/11/25 2:42:24

目录

一、XML映射文件

1.  介绍

2.  MyBatisX插件

二、MyBatis动态SQL

1.  if

2.  foreach

3.  sql & include


一、XML映射文件

1.  介绍

XML映射文件的名称与Mapper接口名称一致,并且将XML映射文件和Mapper接口放置在相同包下(同包同名)

XML映射文件的namespace属性为Mapper接口全限定名一致。

XML映射文件中sql语句的id与Mapper接口中的方法名一致,并保持返回类型一致。

//mybatis中文网
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">


<mapper namespace="com.mybatis.mapper.EmpMapper">
<!--    resultType:单条记录所封装的类型-->
<!--    权限定位名 : 找到对应 -> 右键 -> Copy -> Copy Reference -->
    <select id="list" resultType="com.mybatis.pojo.Emp">
        select * from emp where name like concat('%',#{name},'%') and gender = #{gender} and " +
        "entrydate between #{begin} and #{end} order by update_time desc;
    </select>
</mapper>

使用Mybatis的注解,主要是来完成一些简单的增删改查功能。如果需要实现复杂的SQL功能,建议使用XML来配置映射语句。
官方说明:https://mybatis.net.cn/getting-started.html

2.  MyBatisX插件

① MybatisX 是一款基于IDEA的快速开发Mybatis的插件,为效率而生。

② 安装:

二、MyBatis动态SQL

随着用户的输入或外部条件的变化而变化的SQL语句,我们称为 动态SQL 

<select id="getList" resultType="com.mybatis.pojo.Emp">
        select * from emp where name like concat('%',#{name},'%') and gender = #{gender} and " +
        "entrydate between #{begin} and #{end} order by update_time desc;
    </select>

例如我们之前编写的select语句,where条件是固定的,即使查询时没有指定,也会传递空值null进行查询。而比如我们只想通过name属性进行查询,在查询时后两个条件也会拼接但是传递的是空值null,也是查询不到数据的。

所以我们通过 动态SQL 的三个标签来解决这个问题:

  • <if>
  • <foreach>
  • <sql><include>

1.  if

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

② <where>:where元素只会在子元素有内容的情况下才插入where子句。而且会自动去除子句的开头的AND 或 OR 。

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

<!-- 动态查询-->
    public List<Emp> getList(String name, short gender, LocalDate begin, LocalDate end);

<select id="getList" resultType="com.mybatis.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="begin != null and end != null">
                  and entrydate between #{begin} and #{end}
              </if>
        </where>
        order by update_time desc;
    </select>

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

需求:动态更新员工信息,如果更新时传递有值,则更新;如果更新时没有传递值,则不更新。

解决方案:动态SQL

//动态更新员工 --- 更新ID为18的员工  username:Tom111,name:汤姆111,gender:2
    @Test
    public void testUpdate2(){
        //构建员工对象
        Emp emp = new Emp();
        emp.setId(18);
        emp.setUsername("Tom111");
        emp.setName("汤姆111");
        emp.setGender((short)2);
        emp.setUpdateTime(LocalDateTime.now());

        //执行更新员工信息操作
        empMapper.update(emp);
}

更新后其他值没有传参赋值所以均为空值null,这与我们预期结果不一致。

 使用动态SQL解决问题:

<!-- 动态SQL 动态更新 -->
    public void update2(Emp emp);

<update id="update2">
        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>
        where id = #{id};
        </set>
    </update>

2.  foreach

在我们之前的学习和设计中,批量删除就会用<foreach>标签。

属性:

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

// 批量删除员工
// 实现类
    @Test
    public void testDeleteBuIds(){
        List<Integer> ids = Arrays.asList(13,14,15);
        empMapper.delectByIds(ids);
    }

// 接口方法
public void delectByIds(List<Integer> ids);

//XML映射文件
<delete id="delectByIds">
        delete from emp where id in
        <!--collection:遍历的集合
        item:遍历出来的元素
        separator:分隔符
        open:遍历开始前拼接的sql片段
        close:遍历结束后拼接的sql片段 -->
        <foreach collection="ids" item="id" separator="," open="(" close=")">
            #{id}
        </foreach>
    </delete>

3.  sql & include

问题分析:

<select id="list" resultType="com.mybatis.pojo.Emp">
  select id, username, password, name, gender, image, job, entrydate, dept_ id, create_ _time, update_ _time from emp
  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>
    order by update_ _time desc
</select>

<select id="getByld" resultType="com.mybatis.pojo.Emp">
  select id, username, password, name, gender, image, job, entrydate, dept_ id, create_ _time, update_ _time from emp
  where id = #{id}
</select>

动态条件查询和根据id查询员工信息,直接利用select * 将所有信息字段罗列出来。而且代码也存在重复冗余,代码复用性低。在Java中我们会将重复代码封装到方法中,需要代码逻辑时直接调用。而在MyBatis动态SQL我们同样可以将重复代码抽取然后在原位置重新引入。


① <sql>:定义可重用的SQL片段,指定唯一标识id属性

② <include>:通过属性refid,指定包含的sql片段。

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

    <select id="getList" resultType="com.mybatis.pojo.Emp">
        <include refid="commonSelect"></include>
        <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>

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

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

相关文章

【Java EE】-网络编程(三) TCP/IP协议详解

作者&#xff1a;学Java的冬瓜 博客主页&#xff1a;☀冬瓜的主页&#x1f319; 专栏&#xff1a;【JavaEE】 主要内容&#xff1a;应用层HTTP协议、DNS域名解析系统、传输层UDP协议&#xff0c;TCP协议。TCP协议的工作机制&#xff1a;确认应答、超时重传、连接管理、滑动窗口…

【Linux】MySQL高可用之读写分离监控实践

一、Mycat-web安装配置 1、Mycat节点安装zookeeper&#xff08;在mycat实现了读写分离上安装&#xff09; ① 解压zookeeper压缩包 tar -zxvf zookeeper-3.4.14.tar.gz -C /opt/② cd到cnf目录下将文件复制 ③ cd到bin目录下启动 ./zkServer.sh start2、Mycat节点安装mycat-we…

跨境卖家不可错过的2023开斋节选品和营销技巧,轻松拓展海外市场

开斋节是穆斯林世界最重要的节日之一&#xff0c;同时也是跨境电商一个非常重要的销售节点。在这个节日期间&#xff0c;跨境卖家可以通过合适的选品和营销策略吸引更多的消费者&#xff0c;提高销售额。本文将探讨2023年跨境卖家在开斋节期间如何做好选品和营销。 一、选品 1…

MySQL到ClickHouse数据同步方案对比

ClickHouse 在执行分析查询时的速度优势很好的弥补了 MySQL 的不足&#xff0c;但是对于很多开发者和DBA来说&#xff0c;如何将MySQL稳定、高效、简单的同步到 ClickHouse 却很困难。本文对比了 NineData、MaterializeMySQL&#xff08;ClickHouse自带&#xff09;、Bifrost 三…

下一代听歌识曲技术——从信号处理到深度学习

音乐丰富我们的生活&#xff1b;音乐传达人类的情感&#xff1b;音乐表达人类的艺术。人类文明的进程中离不开音乐这个载体&#xff0c;音乐也离不开人类的真情创作。在听到好听却没听过的歌曲时&#xff0c;如何快速准确得到该歌曲的歌名成为当务之急。LiveVideoStackCon 2022…

网页学习-小试牛刀

网页学习 一、 网页组成二、HTML认知2.1 结构2.2 常用标签2.3 列表标签2.4 表格标签2.5 表单标签2.6 语义化标签2.7 字符实体 三、CSS认知四、JS认知 一、 网页组成 分为三大部分&#xff1a;HTML、CSS和JavaScript。 HTML&#xff08;Hyper Text Markup Language&#xff0c…

根据端口号查询进程路径

研究背景&#xff1a; 在工作的时候&#xff0c;有时候我们会在服务器上部署很多API接口程式&#xff0c;每个程式都有不同的端口号&#xff0c;便于提供服务。当时间久了&#xff0c;我们需要对接口操作的时候&#xff0c;我们有可能会忘掉接口程式所在的路径&#xff0c;而只…

一文掌握如何使用Java操作文件与IO流

文章目录 1. 认识文件2. 文件的类型3. 操作文件3.1 属性3.2 构造方法3.3 常用方法 4. IO流4.1 字节流4.1.1 InputStream4.1.2 OutputStream4.1.3 flush刷新4.1.4 关闭文件close4.1.5 字节缓冲流 4.2 字符流4.2.1 Reader4.2.2 Writer4.2.3 Scanner4.2.4 字符缓冲流 5. 复制文件5…

C语言入门篇——语句篇

目录 1、空语句 2、表达式语句 3、复合语句 4、控制语句 4.1、C控制语句&#xff1a;循环 4.1.1、while 4.1.2、while里的break和continue 4.2.1、for 4.2.2、for里的break和continue 4.3.1、do while 4.3.2、do while里的break和continue 5、C控制语句&#xff1a…

Flink 实时数仓 (一) --------- 数据采集层

目录 一、数仓分层介绍二、实时需求概览三、统计架构分析四、日志数据采集1. 模拟日志生成器的使用2. 日志采集模块-本地测试3. 日志采集模块-打包单机部署 五、业务数据库数据采集1. MySQL 的准备2. 环境搭建3. 代码实现 六、Nginx 安装七、Maxwell 安装八、Canal 安装 一、数…

STM32 平衡小车之电机驱动

TB6612FNG简介 单片机引脚的电流一般只有几十个毫安&#xff0c;无法驱动电机&#xff0c;因此一般是通过单片机控制电机驱动芯片进而控制电机。TB6612是比较常用的电机驱动芯片之一。 TB6612FNG可以同时控制两个电机&#xff0c;工作电流1.2A&#xff0c;最大电流3.2A。 VM电…

通信方式基础知识

文章目录 前言一、分类方式1、串行通信和并行通信2、同步通信和异步通信3、单工、半双工、全双工通信 前言 南京的梧桐树可以鲨掉我的程度 一、分类方式 1、串行通信和并行通信 串行通信&#xff1a;按位顺序&#xff0c;占用引脚资源较少&#xff0c;速度较慢 并行通信&…

移除链表元素(链表篇)

给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 。 示例 1&#xff1a; 思路&#xff1a; ①直接使用原来的链表来进行删除操作。 ②设置一个虚拟头结点在进行删除操作 ①直接使用原来的链表…

【数据结构】- (带头结点)循环双向链表 - 详细实现思路及代码

目录 一、概述 二、循环双向链表 三、循环双向链表实现步骤  &#x1f4cc;3.1 C语言定义循环双向链表结点  &#x1f4cc;3.2 循环双向链表初始化  &#x1f4cc;3.3 循环双向链表插入数据  &#x1f4cc;3.4 循环双向链表删除数据  &#x1f4cc;3.5 循环双向链表查找数…

【python中的多线程了解一下?】

基本说明 线程&#xff08;Thread&#xff09;是操作系统进行调度的最小单位&#xff0c;是进程中的一个独立执行单元。线程与进程相比&#xff0c;具有更轻量级、更高效率、更易调度、共享资源等优点。 在传统的单核CPU中&#xff0c;操作系统通过时间片轮转算法将CPU的时间…

各种通讯总线的学习记要

一、在B站板道题看到一个比较好完视频&#xff08;爱上半导体&#xff09; 我觉得将232和485之前先将串口通信&#xff0c;因为它们都是串口通讯的变种。 串口通讯&#xff1a; 串口通讯我们约定好帧格式和波特率&#xff0c;通讯正常起始位为低开始&#xff0c;8位数据位&a…

【ABAQUS文档阅读笔记】关于体单元、壳单元、梁单元 、truss单元的总体认识

我的主页&#xff1a; 技术邻&#xff1a;小铭的ABAQUS学习的技术邻主页博客园 : HF_SO4的主页哔哩哔哩&#xff1a;小铭的ABAQUS学习的个人空间csdn&#xff1a;qgm1702 博客园文章链接&#xff1a; 学习笔记&#xff0c;from abaqus document “getting start with ABAQUS…

【代码随想录】刷题Day4

1.交换链表 24. 两两交换链表中的节点 前后指针实现 1.没有元素或者只有一个元素无意义 2.给出一个前驱prev&#xff0c;以及用来交换的两个节点cur和next 3.我当时是这么想的&#xff0c;如果两个指针一起动&#xff0c;那么就要用cur和next同时判断结束&#xff0c;也许这个…

C#基础学习--异常

目录 什么是异常 try语句 异常类 catch子句 catch子句段 finally块 为异常寻找处理程序 更进一步搜索 一般法则 抛出异常 不带异常对象的抛出 什么是异常 异常是程序运行时错误&#xff0c;它违反了系统约束或应用程序约束&#xff0c;或出现了在正常操作时未预料的情…

Windows环境下JDK内置迭代器的简介

我是荔园微风&#xff0c;作为一名在IT界整整25年的老兵&#xff0c;今天讨论一下Windows环境下JDK内置迭代器。 相信大家已经注意到&#xff0c;为了让广大程序员能够更加方便地操作聚合对象&#xff0c;在Java、C#等编程语言中都提供了内置迭代器。 如果对这种迭代器还不了…