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

news/2024/10/21 10:01:51/

问题:
有的时候我们需要实现批量删除: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类的属性名。

测试代码

@Testpublic 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但后面地不会去除。

测试代码:

@Testpublic 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会不会智能去除?

测试代码

@Testpublic 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>

测试代码

@Testpublic 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>

测试代码

@Testpublic 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>

测试代码

@Testpublic 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>

测试代码

@Testpublic 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>

测试代码

@Testpublic 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.ppmy.cn/news/89987.html

相关文章

论文分享 | 视野约束下多机器人系统的最小持久图生成与编队控制

阿木推出的Prometheus项目校园赞助活动&#xff0c;再次迎来开发者参与&#xff01; 北京理工大学自动化学院赵欣悦同学&#xff0c;在Prometheus开源仿真架构的基础上进行了二次开发&#xff0c;且使用P450进行了真机实验并发表了相关论文&#xff0c;其论文《视野约束下多机…

python 处理超大文件

1、生成器 处理超大文件 当处理超大文件时&#xff0c;使用生成器可以避免将整个文件读入内存中&#xff0c;从而减少内存占用&#xff0c;提高程序的效率。 生成器是一种特殊的迭代器&#xff0c;可以通过函数来生成一系列的值&#xff0c;而不需要一次性生成所有值。在处理超…

[论文阅读] Explicit Visual Prompting for Low-Level Structure Segmentations

[论文地址] [代码] [CVPR 23] Abstract 我们考虑了检测图像中低层次结构的通用问题&#xff0c;其中包括分割被操纵的部分&#xff0c;识别失焦像素&#xff0c;分离阴影区域&#xff0c;以及检测隐藏的物体。每个问题通常都有一个特定领域的解决方案&#xff0c;我们表明&am…

【Netty】Netty 解码器(十二)

文章目录 前言一、编解码概述1.1、编解码器概述1.2、Netty 内嵌的编码器 二、解码器2.1、ByteToMessageDecoder 抽象类2.1.1、常用方法2.1.2、将字节转为整形的解码器示例 三、ReplayingDecoder 抽象类四、MessageToMessageDecoder 抽象类总结 前言 回顾Netty系列文章&#xf…

快速上手,使用关键字驱动测试框架作为Web应用程序的自动化测试武器

目录 前言&#xff1a; 一、预备知识 二、关键字驱动测试框架 三、关键字驱动测试脚本 四、总结 前言&#xff1a; 自动化测试是软件测试中的重要环节之一&#xff0c;它可以帮助开发人员提高测试效率&#xff0c;节省时间和人力成本。随着互联网的发展&#xff0c;Web应…

智能排班系统 【管理系统功能、操作说明——下篇】

文章目录 页面与功能展示排班日历月视图&#xff08;按职位查询&#xff09;月视图&#xff08;按员工查询&#xff09;周视图 排班任务管理创建排班计算任务设置任务的排班规则设置工作日客流量导入任务计算查看任务结果发布任务任务多算法计算 页面与功能展示 排班日历 在排…

Tomcat的讲解与安装

文章目录 前言一.Tomcat是什么二.Tomcat的原理三.Tomcat的安装和说明**1.下载****2.解压安装**bin目录conf目录lib目录log目录temp目录webapps目录work目录 3.配置环境变量 四.验证安装 前言 Tomcat 是一个 HTTP 服务器. 前面我们已经学习了 HTTP 协议, 知道了 HTTP 协议就是 …

Spring Cloud Eureka 是什么?如何使用它来实现服务注册与发现?

Spring Cloud Eureka 是什么&#xff1f;如何使用它来实现服务注册与发现&#xff1f; 在微服务架构中&#xff0c;服务注册与发现是一个非常重要的概念。它可以帮助我们实现服务的自动发现和负载均衡&#xff0c;从而提高系统的可用性和可扩展性。Spring Cloud Eureka 是一个…