MyBatis动态SQL,基本语法加实战,一篇搞懂

news2025/1/11 11:21:05

问题:
有的时候我们需要实现批量删除:delete from t_car where id in(1,2,3,4,5,6,…这⾥的值是动态的,根据⽤户选择的
id不同,值是不同的);
多条件查询:有时我们需要根据多个不同地条件来进行查询,比如:select * from t_car where brand like ‘丰⽥%’ and guide_price > 30 and …;
以上情况地sql语句都是动态的,因此需要我们来进行SQL语句的动态拼接。在MyBatis中是通过不同标签来实现SQL语句的动态的。下面来一一讨论使用标签。

准备工作

在这里插入图片描述
在这里插入图片描述

几种常用标签

if标签

需求:多条件查询。
可能的条件包括:记录id(id)、指导价格(guide_price)、汽⻋类型(car_type)

实战
CarMapper接口中方法

 /***
     * 多条件查询
     * @param id
     * @param brand
     * @param guidePrice
     * @return
     */
    List<Car> multiConditionSelect(@Param("id") Long id,@Param("brand") String brand,@Param("guidePrice") Double guidePrice);

SQL语句映射文件代码

<select id="multiConditionSelect" resultType="Car">
        select * from t_car where
        <if test="id != null and id != ''">
            id = #{id}
        </if>
        <if test="brand != null and brand != ''">
            and brand like "%"#{brand}"%"
        </if>
        <if test="guidePrice != null and guidePrice != ''">
            and guide_price > #{guidePrice}
        </if>
    </select>

基本语法:test后面语句的结果如果为true,则该if标签的语句生效,否则不生效。
细节:if标签test后面中的变量是@param起的别名,如果没用@param就是系统默认的arf0…param1…,如果参数是bean类则test后面的变量是bean类的属性名。

测试代码

@Test
    public void testMultiConditionSelect(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        List<Car> cars = mapper.multiConditionSelect(59L,"大众",5.0);
        cars.forEach(car -> System.out.println(car));
        sqlSession.close();
    }

可以看出三个参数都不为空,且不为null,执行一下看一下结果
在这里插入图片描述
可以看出sql语句和预想的一样。

我们将测试代码中

        List<Car> cars = mapper.multiConditionSelect(59L,"大众",5.0);

的第一个参数置空,并再次执行,结果如下
在这里插入图片描述
因为我们将第一个参数置空后SQL语句变为了 select * from t_car where and brand like “%”?“%” and guide_price > ? 可以看出多了一个and,如何解决呢?很简单,我们只需要在where后面加上 1=1 就可以了。更改后再次执行,结果如下
在这里插入图片描述
成功解决

但是这样的话我们需要在第一个条件前面也加上and,否则第一个条件不为空的时候也会出错

where标签

where标签的作⽤:让where⼦句更加动态智能。
所有条件都为空时,where标签保证不会⽣成where⼦句。
⾃动去除某些条件前⾯多余的and或or。

在上面if语句的使用中我们发现每个条件前面加不加and是个麻烦的事情,where标签很好地解决了上面地问题

CarMapper接口中方法

/***
     * 使用Where标签,使Where子句更加智能
     * @param id
     * @param brand
     * @param guidePrice
     * @return
     */
    List<Car> multiConditionSelectWithWhere(@Param("id") Long id,@Param("brand") String brand,@Param("guidePrice") Double guidePrice);

SQL映射文件中代码

<select id="multiConditionSelectWithWhere" resultType="Car">
        select * from t_car
        <where>
            <if test="id != null and id != ''">
                and id = #{id}
            </if>
            <if test="brand != null and brand != ''">
                and brand like "%"#{brand}"%"
            </if>
            <if test="guidePrice != null and guidePrice != ''">
                and guide_price > #{guidePrice}
            </if>
        </where>
    </select>

细节解析:使用where标签,会自动地在t_car后面添加去除where,当后面条件为空,where不会生成,反之生成,同时还会智能去除某些情况下if子句中前面地and但后面地不会去除。

测试代码:

@Test
    public void testMultiConditionSelectWithWhere(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        List<Car> cars = mapper.multiConditionSelectWithWhere(null,"",null);
        cars.forEach(car -> System.out.println(car));
        sqlSession.close();
    }

执行结果
在这里插入图片描述
可以看出在三个参数都为空地情况下where子句智能地没有添加,其他情况不在一一测试。

trim 标签

基本语法
trim标签的属性:
prefix:在trim标签中的语句前添加内容
suffix:在trim标签中的语句后添加内容
prefixOverrides:前缀覆盖掉(去掉)
suffixOverrides:后缀覆盖掉(去掉)

实战
CarMapper接口中方法代码

/***
     * 根据多条件啊查询使用trim标签
     * @param id
     * @param brand
     * @param guidePrice
     * @return
     */
    List<Car> multiConditionSelectWithTrim(@Param("id") Long id,@Param("brand") String brand,@Param("guidePrice") Double guidePrice);

SQL语句映射文件中代码

<select id="multiConditionSelectWithTrim" resultType="Car">
        select * from t_car
        <trim prefix="where" suffixOverrides="and">
            <if test="id != null and id != ''">
                id = #{id} and
            </if>
            <if test="brand != null and brand != ''">
                brand like "%"#{brand}"%" and
            </if>
            <if test="guidePrice != null and guidePrice != ''">
                guide_price > #{guidePrice}
            </if>
        </trim>
    </select>

prefix="where"加一个前缀,在t_car后面我们就不用自己写where了

suffixOverrides=“and” 去除某些条件后面地and,如果第一个第三个参数都为空,第二个条件后面地and会不会智能去除?

测试代码

@Test
    public void testMultiConditionSelectWithTrim(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        List<Car> cars = mapper.multiConditionSelectWithTrim(null,"大众",null);
        cars.forEach(car -> System.out.println(car));
        sqlSession.close();
    }

测试结果
在这里插入图片描述
显然智能去除了第二个条件后面的and,如果三个条件都为空,前缀where还会添加吗?答案是否定地,不会添加,trim标签还是很智能地

set标签

语法
1.主要使⽤在update语句当中,⽤来⽣成set关键字,同时去掉最后多余的“,”

需求:⽐如我们只更新提交的不为空的字段,如果提交的数据是空或者"",那么这个字段我们将不更新。(set标签if标签混用)
实战

CarMapper接口中方法代码

/***
     * 使用set标签完成根据id修改记录
     * <set><set/>生成set同时去掉多余  ,
     * @return
     */
    int updateBySet(Car car);

SQL语句映射文件中代码

<update id="updateBySet">
        update t_car
        <set>
            <if test="carNum != null and carNum != ''">car_num = #{carNum},</if>
            <if test="Brand != null and Brand != ''">brand = #{Brand},</if>
            <if test="guidePrice != null and guidePrice != ''">guide_price = #{guidePrice},</if>
            <if test="produceTime != null and produceTime != ''">produce_time = #{produceTime},</if>
            <if test="carType != null and carType != ''">car_type = #{carType},</if>
        </set>
        where id = #{id}
    </update>

测试代码

@Test
    public void TestUpdateBySet(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        Car car = new Car(59L,"7777",null,null,null,null);
        int count = mapper.updateBySet(car);
        System.out.println("成功" + count + "条");
        sqlSession.commit();
        sqlSession.close();
    }

执行结果
在这里插入图片描述
在这里插入图片描述

可以看出生成了set并且语句后面多余地’ , '被智能去除

choose when oterwise标签

基本语法
三者一块使用

语法格式

<choose>
 <when></when>
 <when></when>
 <when></when>
 <otherwise></otherwise>
</choose>

相当于

if(){
 
}else if(){
 
}else if(){
 
}else if(){
 
}else{
}

只有⼀个分⽀会被选择!!!!
需求:先根据品牌查询,如果没有提供品牌,再根据指导价格查询,如果没有提供指导价格,就根据⽣
产⽇期查询。
实战

CarMapper接口中方法

/***
     * 使用choose 标签进行查询
     * @return
     */
    List<Car> selectWithChoose(@Param("brand") String brand,@Param("guidePrice") Double guidePrice,@Param("carType") String carType);

SQL映射文件中代码

<select id="selectWithChoose" resultType="Car">
        select * from t_car
        <where>
            <choose>
                <when test="brand != '' and brand != null">
                    brand like "%"#{brand}"%"
                </when>
                <when test="guidePrice != '' and guidePrice != null">
                    guide_price > #{guidePrice}
                </when>
                <otherwise>
                    car_type = #{carType}
                </otherwise>
            </choose>
        </where>
    </select>

测试代码

@Test
    public void testSelectWithChoose(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        List<Car> cars = mapper.selectWithChoose("",null,"新能源");
        cars.forEach(car -> System.out.println(car));
        sqlSession.close();
    }

执行结果
在这里插入图片描述

foreach标签

基本用法
和java中地foreach类似,一共有五个参数,解释如下
collection:集合或数组
item:集合或数组中的元素
separator:分隔符
open:foreach标签中所有内容的开始
close:foreach标签中所有内容的结束

需求

批量添加

insert into t_car values
 (null,'1001','凯美瑞',35.0,'2010-10-11','燃油⻋'),
 (null,'1002','⽐亚迪唐',31.0,'2020-11-11','新能源'),
 (null,'1003','⽐亚迪宋',32.0,'2020-10-11','新能源')

实战

CarMapper接口中方法代码

/***
     * 利用foreach标签进行批量插入
     * @return
     */
    int insertBatchByForeach(@Param("cars") List<Car> cars);

SQL映射文件中代码

<insert id="insertBatchByForeach">
        insert into t_car values
        <foreach collection="cars" item="car" separator=",">
            (null,#{car.carNum},#{car.brand},#{car.guidePrice},#{car.produceTime},#{car.carType})
        </foreach>
    </insert>

测试代码

@Test
    public void testInsertBatchByForeach(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        Car car1 = new Car(null,"1100","拖拉机1",10.0,"2001-10-11","燃油车");
        Car car2 = new Car(null,"1100","拖拉机2",10.0,"2001-10-11","燃油车");
        Car car3 = new Car(null,"1100","拖拉机3",10.0,"2001-10-11","燃油车");
        List<Car> cars = new ArrayList<>();
        cars.add(car1);
        cars.add(car2);
        cars.add(car3);
        mapper.insertBatchByForeach(cars);
        sqlSession.commit();
        sqlSession.close();
    }

执行结果
在这里插入图片描述
在这里插入图片描述
大家注意拼接成地sql语句还是很好理解的
需求
批量删除 分别使用or和in

delete from t_car where id in(1,2,3);
delete from t_car where id = 1 or id = 2 or id = 3;

实战1(使用in)
CarMapper接口中的方法代码

/***
     * 利用foreach进行批量删除
     * in(id1,id2.....)
     * @param ids
     * @return
     */
    int deleteBatchByForeach(@Param("ids") Long[] ids);

SQL映射文件代码

<delete id="deleteBatchByForeach">
        delete from t_car
        <where>
            id in
            <foreach collection="ids" item="id" separator="," open="(" close=")">
                #{id}
            </foreach>
        </where>
    </delete>

测试代码

@Test
    public void testDeleteBatchByForeach(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        Long[] ids = {68L,69L,70L};
        int count = mapper.deleteBatchByForeach(ids);
        System.out.println(count);
        sqlSession.commit();
        sqlSession.close();
    }

执行结果
在这里插入图片描述
在这里插入图片描述
实战2 使用or实现批量删除
CarMapper接口中方法代码

/***
     * 利用foreach进行批量删除
     * or
     * @param ids
     * @return
     */
    int deleteBatchByForeach2(@Param("ids") Long[] ids);

SQL映射文件中代码

<delete id="deleteBatchByForeach2">
        delete from t_car where
        <foreach collection="ids" item="id" separator="or">
            id = #{id}
        </foreach>
    </delete>

测试代码

@Test
    public void testDeleteBatchByForeach2(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        Long[] ids = {71L,72L,73L};
        int count = mapper.deleteBatchByForeach2(ids);
        System.out.println(count);
        sqlSession.commit();
        sqlSession.close();
    }

测试结果
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
将基本语法与测试结果中拼接的sql语句一块理解,还是很好理解的😊

sql标签与include标签

基本用法:
sql标签⽤来声明sql⽚段
include标签⽤来将声明的sql⽚段包含到某个sql语句当中
作⽤:代码复⽤。易维护。

SQL映射文件中代码

<sql id="carCols">id,car_num carNum,brand,guide_price guidePrice,produce_t
ime produceTime,car_type carType</sql>
<select id="selectAllRetMap" resultType="map">
 select <include refid="carCols"/> from t_car
</select>
<select id="selectAllRetListMap" resultType="map">
 select <include refid="carCols"/> carType from t_car
</select>
<select id="selectByIdRetMap" resultType="map">
 select <include refid="carCols"/> from t_car where id = #{id}
</select>

总结结束,希望对你能有所帮助

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

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

相关文章

数据集成平台之kettle优缺点分析

数据集成平台前言 数据在业务中发挥着重要的作用&#xff0c;但并非所有数据都具有相同的价值和影响力。事实上&#xff0c;大部分数据业务的核心价值主要来自其中的少部分关键数据。这些关键数据可能包含着重要的业务指标、关键客户信息、市场趋势数据等&#xff0c;它们直接…

【机器学习】之Anaconda中使用的命令

操作之前&#xff0c;点击上图入口&#xff0c;进入Prompt。 //示例是在base环境下&#xff0c;cls清屏 (base) C:\Users\bubusa>cls1、base环境下的操作 //&#xff08;1&#xff09;列出所有虚拟环境 (base) C:\Users\bubusa>conda env list # conda environments: #…

Radeon Vii 系统分析 001记——工具

0. 简介 为了对 vega 7nm 有更感性的编程使用体验&#xff0c;故对 vega 7nm做各种测试&#xff1b; 工具&#xff1a; CLRadeonExtender ubuntu ROCm 资料&#xff1a; &#xff08;1&#xff09; 一张安装了 Radeon Vii vega 7nm 的台式机&#xff0c;win10 或 ubunt…

Mit6.006-lecture08-BinaryHeaps

一、优先队列接口 记录一些项目&#xff0c;快速地访问/移除最重要的 例&#xff1a;有限带宽的路由器&#xff0c;必须优先某些信息 例&#xff1a;操作系统内核中的进程调度 例&#xff1a;离散事件模拟&#xff08;下一件事何时发生&#xff09; 例&#xff1a;图算法&am…

js程序运行时在本机与外部app交互

js程序运行时在本机与外部app交互 目录 js程序运行时在本机与外部app交互 一、序言 1.1、问题 1.2、简要回答 二、原理 2.1、插件/web扩展/应用配置/权限 2.2、获取权限-原生应用交换信息的权限nativeMessaging 2.2.1、runtime(运行时的API) 2.3、连接本地应用程序的…

《微服务实战》 第十四章 RabbitMQ应用

前言 一般MQ用于系统解耦、削峰使用,常见于微服务、业务活动等场景。 1、RabbitMQ概念概念 RabbitMQ整体上是一个生产者与消费者模型,主要负责接收、存储和转发消息。 1.1、生产者和消费者 Producer:生产者,就是投递消息的一方。消息一般可以包含2个部分:消息体和标签…

Vue3+i18n多语言动态国际化设置步骤

1、技术介绍 i18n&#xff1a;Vue.js 的国际化插件。它可以轻松地将一些本地化功能集成到你的 Vue.js 应用程序中 i18n的官网地址安装 | Vue I18n (kazupon.github.io) 2、插件安装 npm install vue-i18n9 --save需要注意的是vue3最好使用9.x以上的版本&#xff01; 3、创建i…

夏日挂脖风扇方案开发设计

夏日挂脖风扇是一种便携式的风扇设备&#xff0c;通过挂在用户的脖子上&#xff0c;为用户提供清凉的风力降温。在夏季高温天气中&#xff0c;挂脖风扇成为了人们追逐的热门产品之一。为了满足市场需求&#xff0c;夏日挂脖风扇的方案开发设计需要考虑多个方面&#xff0c;包括…

Class 09 - Data Frame和查看数据

Class 09 - Data Frame和查看数据 DataFrametibbleshead()str()colnames()mutate()创建 Dataframe DataFrame 在我们开始做数据清洗或者检查数据是否存在偏差之前&#xff0c;我们需要先将我们的数据转换成合适的格式方便我们做后续的处理。 这就要说到DataFrame了。因为他很…

CSDN programmer_ada what the hell

CSDN programmer_ada 1、今天博客收到了1条评论&#xff0c;莫名其妙。2、查看这个账户 原来是CSDN官方机器人3、貌似领了红包 就会自动关注发红包的账户 1、今天博客收到了1条评论&#xff0c;莫名其妙。 一定要坚持创作更多高质量博客哦, 小小红包, 以资鼓励, 更多创作活动请…

【ClickHouse】什么是ClickHouse?CK入门

文章目录 一、ClickHouse入门1、列式存储2、DBMS的功能3、多样化引擎4、高吞吐写入能力5、数据分区与线程级并行6、性能对比7、官网 二、ClickHouse安装1、准备工作2、单机安装 三、ClickHouse的数据类型1、整型2、浮点型3、布尔型4、Decimal型6、枚举类型7、时间类型8、数组 一…

好程序员:女生学Java好学吗?女生学Java有什么优势?

小源经常会听到女生咨询适不适合学习Java开发的问题&#xff0c;提出这种问题归根结底还是缺乏性别自信&#xff0c;默认女性比男性弱。实际上这个问题并不存在&#xff0c;男女平等才是正确的思维&#xff0c;当然&#xff0c;也为了解开女生们的心结&#xff0c;这里好程序员…

开发微信公众号本地调试+-+cpolar内网穿透

文章目录 前言1. 配置本地服务器2. 内网穿透2.1 下载安装cpolar内网穿透2.2 创建隧道 3. 测试公网访问4. 固定域名4.1 保留一个二级子域名4.2 配置二级子域名 5. 使用固定二级子域名进行微信开发 转载自cpolar内网穿透的文章&#xff1a;微信公众号开发&#xff1a;对接本地开发…

股票?看我用python采集数据制作成交量图表

前言 嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 开发环境 & 第三方模块: 解释器版本: python 3.8 代码编辑器: pycharm 2021.2 requests: pip install requests 爬虫 pyecharts: pip install pyecharts 数据分析 pandas: pip install pandas 数据分析 基本流…

C++常用的支持中文的GUI库Qt 6之一:下载、安装与简单使用

C常用的支持中文的GUI库Qt 6之一&#xff1a;下载、安装与简单使用 因为Qt发展变化较快&#xff0c;网上许多介绍Qt的下载、安装与使用已过时&#xff0c;初学者常因行不通而受挫&#xff0c;故此发布本文&#xff0c;以Qt 6.2.4开源版在Windows 10安装与使用为例介绍。 C好用…

Kubernetes 之7大CNI 网络插件用法和对比

Kubernetes 它需要网络插件来提供集群内部和集群外部的网络通信。以下是一些常用的 k8s 网络插件&#xff1a; Flannel&#xff1a;Flannel 是最常用的 k8s 网络插件之一&#xff0c;它使用了虚拟网络技术来实现容器之间的通信&#xff0c;支持多种网络后端&#xff0c;如 VXLA…

SpringSecurity权限管理基本概念和整体架构介绍

文章目录 一、权限管理1、认证2、授权3、对权限控制&#xff0c;现有的解决方案 二、SpringSecurity简介1、官方定义2、历史 三、整体架构1、认证AuthenticationManagerAuthenticationSecurityContextHolder 2、授权AccessDecisionManagerAccessDecisionVoterConfigAttribute 一…

SQL注入:sqli第一关详细讲解

一、实验环境&#xff1a; Apache2.4.39 FTP0.9.60 MySQL5.7.26 PHP 5.3.29(注意PHP的版本不应过高&#xff0c;否则会导致sqli安装失败) sqli 二、实验步骤 第一步&#xff1a;在id1后加入一个闭合符号&#xff0c;如果报错&#xff0c;再在后面加上 -- qwe将后面注释掉…

vivado中的FPGA时钟管理单元PLL学习记录

vivado中的FPGA时钟管理单元PLL学习记录 CMT简介一、PLL IP的使用1、ip调用 2、生成的频率限制二、PLL实现原理 三、使用过程中的问题程序注意事项 CMT简介 FPGA中时钟管理模块&#xff08;CMT&#xff09;包括PLL和MMCM&#xff0c;用于将时钟倍频(比如输入时钟25M&#xff0…

第三方实验室云LIS系统

本套云LIS系统基于B/S架构的实验室管理系统&#xff0c;整个系统的运行基于WEB层面&#xff0c;只需要在对应的工作台安装一个浏览器软件有外网即可访问。SaaS服务&#xff0c;无需部署&#xff0c;开通账号接口快速入门使用&#xff0c;集齐前处理、检验、报告、质控、统计分析…