详细分析Mybatis中的<foreach>标签
目录
- 前言
- 1. 基本语法
- 2. Demo
- 3. 实际例子
前言
对于Java专栏:Java专栏
对于Mybatis的相关知识可看我之前的文章:Mybatis从入门到精通(全)
对于其余Java框架可看我之前的文章:java框架 零基础从入门到精通的学习路线 附开源项目面经等(超全)
对于上述Mybatis中曾有讲过foreach标签!此篇博客对其标签进行拓展
1. 基本语法
MyBatis中的<foreach>
标签是用于迭代集合或数组的元素,生成对应的SQL片段,以便在动态SQL中使用。
该标签通常用于循环处理参数集合,生成多个相同的SQL片段,以实现批量操作或动态条件查询。
其基本的语法如下:
<foreach collection="collectionName" item="itemName" index="indexName" open="(" close=")" separator=",">#{itemName}
</foreach>
对应的属性如下:(只有collection和item是必选,其他都是可选参数)
collection
: 指定要迭代的集合或数组的属性名,表示传入的参数的数据类型。
该属性是必须指定的,用于指定要进行foreach操作的对象。item
: 指定在迭代过程中每个元素的别名,表示本次迭代获取的元素。
若collection为List、Set或者数组,则表示其中的元素;
若collection为map,则代表key-value的value。
该参数是必选的。index
: 指定在迭代过程中每个元素的索引,仅对集合有效。
在遍历List时,index表示元素的索引;在遍历Map时,index表示Map的key。该参数是可选的。open
: 指定迭代开始时的字符串,最常用的是左括弧'('
。
MyBatis会将该字符拼接到整体的SQL语句之前,并且只拼接一次。该参数是可选的。close
: 指定迭代结束时的字符串,最常用的是右括弧')'
。
MyBatis会将该字符拼接到整体的SQL语句之后。该参数是可选的。separator
: 指定每次迭代之间的分隔符。
在SQL语句中,用于分隔不同元素的值。例如,1,2,3之间的,。该参数是可选的。
2. Demo
下面是一个简单的例子,假设有一个包含多个用户ID的集合,我们想要生成一个SQL语句查询这些用户:
<select id="selectUsersByIds" resultType="User">SELECT * FROM usersWHERE id IN<foreach collection="userIds" item="userId" open="(" close=")" separator=",">#{userId}</foreach>
</select>
在这个例子中,userIds是一个包含用户ID的集合,<foreach>
标签会生成类似于IN (id1, id2, id3)的SQL片段。
另外,如果使用MyBatis的动态SQL功能,可以在<if>
标签内使用<foreach>
,以根据条件动态生成SQL片段,以下是一个例子,假设有一个条件查询的场景,根据用户选择的角色列表进行查询:
<select id="selectUsersByRoles" resultType="User">SELECT * FROM users<where><if test="roles != null and roles.size > 0">AND id IN<foreach collection="roles" item="role" open="(" close=")" separator=",">#{role}</foreach></if></where>
</select>
在这个例子中,selectUsersByRoles是一个动态SQL查询,它根据用户传入的roles参数动态生成SQL条件。
- 如果roles不为空且包含元素,那么
<if>
标签内的内容会生效,生成类似于AND id IN (role1, role2, role3)
的SQL片段。 - 如果roles为空或不包含元素,该条件会被忽略,从而生成不包含AND的SQL语句。
在实际应用中,这种动态SQL的使用可以根据不同的业务需求动态构建查询条件,使SQL语句更加灵活和可复用。
3. 实际例子
结合实战中的例子,讲解更加透彻
批量插入
,即列表中有多个元素,代码示例:
<insert id="saveForList" parameterType="java.util.List">INSERT INTO E_DEVICE_TEMP_ALARM_HIST(DEVICE_NAME, BATTERY_TEMP, SEND_TO_DRIVER, CREATE_TIME, UPDATE_TIME, SENDER, SUGGESTION)<foreach collection="temperatureAlarmHistList" item="temperatureAlarmHist" separator="union all" open="(" close=")">SELECT#{temperatureAlarmHist.deviceName, jdbcType=VARCHAR},#{temperatureAlarmHist.batteryTemp, jdbcType=VARCHAR},#{temperatureAlarmHist.sendToDriver, jdbcType=INTEGER},#{temperatureAlarmHist.createTime, jdbcType=DATE},#{temperatureAlarmHist.updateTime, jdbcType=DATE},#{temperatureAlarmHist.sender, jdbcType=VARCHAR},#{temperatureAlarmHist.suggestion, jdbcType=VARCHAR}FROM DUAL</foreach>
</insert>
动态SQL语句
,更新语句也同理:
<update id="removeRuleDetailByRuleId" >update equipment_change_shifts_rule_detail set is_deleted = 1 where rule_id IN<foreach collection="ids" item="id" index="index" open="(" separator="," close=")">#{id}</foreach>
</update>
结合if语句
,且参数位置可以随意:
<select id="trees" resultMap="treeNodeResultMap">select id, parent_id, equipment_name as title, id as 'value', id as 'key',location from equipment_architecture where is_deleted = 0<if test="tenantId!=null">and tenant_id = #{tenantId}</if>and id in<foreach close=")" collection="ids" item="listItem" open="(" separator=",">#{listItem}</foreach>
</select>
相关文章:
详细分析Mybatis中的<foreach>标签
目录 前言1. 基本语法2. Demo3. 实际例子 前言 对于Java专栏:Java专栏 对于Mybatis的相关知识可看我之前的文章:Mybatis从入门到精通(全) 对于其余Java框架可看我之前的文章:java框架 零基础从入门到精通的学习路线 附…...
linux-挂载Samba共享
linux-挂载Samba共享 1、linux服务器启动Samba共享服务 2、客户端电脑安装cifs-utils dnf install cifs-utils # 或 yum install cifs-utils3、挂载共享目录 # 创建挂目录 mkdir /share # 使用mount命令挂在共享目录,-t协议类型 -o用户名密码 共享目录访问地址 挂…...

Java入门IDEA基础语法
1:Java入门 1.1 Java简介 Java是什么: Java是一门非常优秀的计算机语言 语言:人与人交流沟通的表达方式 计算机语言:人与计算机之间进行信息交流沟通的一种特殊语言 Java之父:詹姆斯高斯林(James Gosli…...

【小白专用】C# 连接 MySQL 数据库
C# – Mysql 数据库连接 1. 配置环境 #前提:电脑已安装Mysql服务; Visual Studio 安装Mysql依赖库: 工具 -> NuGet 包管理器 -> 管理解决方案的 NuGet程序包 —> 搜索, 安装Mysql.Data (Oracle); (安装成功后&…...
Django登录注销视图
Django在身份验证框架中包含了一些你可以直接使用的表单和视图。在大多数情况下,可以使用默认的Django认证视图。 Django在django.contrib.auth.views提供了以下基于类的视图来处理身份验证: LoginView:处理登录表单并登录用户 LogoutView&a…...
云原生到底是什么意思
云原生到底是什么意思? 引言 随着云计算技术的迅速发展,云原生成为了一个备受关注的话题。云原生不仅仅是一种新的软件架构,更是一种变革性的开发方法论。本文将深入解析云原生的意义、特点以及为什么它在现代软件开发中变得如此重要。 云…...

【银行测试】银行项目,信用卡业务测试+常问面试(三)
目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 银行测试-信用卡业…...

AI大模型学习笔记之二:什么是 AI 大模型的训练和推理?
在人工智能(AI)的领域中,我们经常听到训练(Training) 和 推理(Inference) 这两个词汇,它们是构建强大 AI 模型的关键步骤。我们通过类比人类的学习过程来理解这两个概念,可以更加自然而生动地理…...

【MATLAB源码-第113期】基于matlab的孔雀优化算法(POA)机器人栅格路径规划,输出做短路径图和适应度曲线。
操作环境: MATLAB 2022a 1、算法描述 POA(孔雀优化算法)是一种基于孔雀羽毛开屏行为启发的优化算法。这种算法模仿孔雀通过展开其色彩斑斓的尾羽来吸引雌性的自然行为。在算法中,每个孔雀代表一个潜在的解决方案,而…...

iphone 5s的充电时序原理图纸,iPAD充电讲解
上一篇写了iphone 5的时序。那是电池供电的开机时序。iphone 5s也是差不多的过程,不说了。现在看iphone5s手机充电时候的时序。iphone5s充电比iphone5充电简单了很多。 首先是usb接口接到手机上,usb线连接到J7接口上。J7接口不只是接usb,还能…...

react基础入门
1,了解react react并不是一个MVC框架,他只是一个很强大的javaScript库,主要作用是用来构建UI界面。 react的核心是封装一个个大大小小的组件(小到一个按钮,大到一个页面)来构建复杂的UI界面,每…...

spring boot学习第八篇:通过spring boot、jedis实现秒单
参考:Redis实现分布式锁的7种方案 - 知乎 1、 准备数据库表,如下SQL表示库存表,有主键ID和库存数量字段 CREATE TABLE t_stock (id bigint(20) NOT NULL AUTO_INCREMENT,quantity bigint(20) NOT NULL,PRIMARY KEY (id) ) ENGINEInnoDB DEF…...
NineAi 新版AI系统网站源码 ChatGPT
简介: Nine AI.ChatGPT是基于ChatGPT开发的一个人工智能技术驱动的自然语言处理工具,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,真正像人类一样来聊天交流,甚至能完成撰写邮件、视频脚本、文案、翻译、代码,写论文等任务。 NineAi 新版A…...
开源监控服务一瞥:Prometheus、Grafana、Zabbix、Nagios、Icinga和Open-Falcon
前言 随着信息技术的发展,监控服务在维护系统稳定性和性能方面变得越来越重要。本文将比较一些流行的开源监控服务,以帮助你选择适合你需求的解决方案。 监控服务对比 监控服务特点优势不足性能扩展性安全性Prometheus- 多维度数据模型- 监控容器化环…...

使用WAF防御网络上的隐蔽威胁之扫描器
在网络安全领域,扫描器是用于侦察和识别网络系统漏洞的工具。 它们可以帮助网络管理员识别安全漏洞,也可能被攻击者用来寻找攻击目标。 扫描器的基本概念 定义:扫描器是一种自动化工具,用于探测网络和服务器中的漏洞、开放端口、…...
企业信息安全管理制度
随着信息化程度的日益推进,企业信息的脆弱性也日益暴露。如何规范日趋复杂的信息安全保障体系建设,如何进行信息风险评估保护企业的信息资产不受侵害,已成为当前行业实现信息化运作亟待解决的问题。 一、企业的信息及其安全隐患 在我公司&am…...
Qt中的线程池
Qt中的线程池 目录 1 为什么需要线程池 2 Qt中有哪些方式实现线程池 3 如何通过QThreadPool类实现线程池 4 如何通过QtConcurrent库实现线程池 5 如何通过自定义的方式实现线程池 5 小结 1 为什么需要线程池 线程池是多线程编程中常用的一种技术,可以帮助管理系统中…...
使用Spring Boot集成中间件:Elasticsearch基础->提高篇
使用Spring Boot集成中间件:Elasticsearch基础->提高篇 导言 Elasticsearch是一个开源的分布式搜索和分析引擎,广泛用于构建实时的搜索和分析应用。在本篇博客中,我们将深入讲解如何使用Spring Boot集成Elasticsearch,实现数…...

【Docker】Dockerfile构建最小镜像
🥳🥳Welcome 的Huihuis Code World ! !🥳🥳 接下来看看由辉辉所写的关于Docker的相关操作吧 目录 🥳🥳Welcome 的Huihuis Code World ! !🥳🥳 前言 一.Dockerfile是什么 二.Dock…...
【严重】GitLab 以其他用户身份执行 Slack 命令
漏洞描述 GitLab 是由GitLab公司开发的、基于Git的集成软件开发平台。使用 Slack 命令在 Slack 聊天环境中运行常见的 GitLab 操作。 GitLab 受影响版本中,由于配置Slack/Mattermost 集成时,未正确验证用户身份信息,导致攻击者可以使用其他…...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序
一、开发准备 环境搭建: 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 项目创建: File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...

STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...
laravel8+vue3.0+element-plus搭建方法
创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...
《C++ 模板》
目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板,就像一个模具,里面可以将不同类型的材料做成一个形状,其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式:templa…...
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要: 近期,在使用较新版本的OpenSSH客户端连接老旧SSH服务器时,会遇到 "no matching key exchange method found", "n…...

C++ 设计模式 《小明的奶茶加料风波》
👨🎓 模式名称:装饰器模式(Decorator Pattern) 👦 小明最近上线了校园奶茶配送功能,业务火爆,大家都在加料: 有的同学要加波霸 🟤,有的要加椰果…...
Kafka主题运维全指南:从基础配置到故障处理
#作者:张桐瑞 文章目录 主题日常管理1. 修改主题分区。2. 修改主题级别参数。3. 变更副本数。4. 修改主题限速。5.主题分区迁移。6. 常见主题错误处理常见错误1:主题删除失败。常见错误2:__consumer_offsets占用太多的磁盘。 主题日常管理 …...
LCTF液晶可调谐滤波器在多光谱相机捕捉无人机目标检测中的作用
中达瑞和自2005年成立以来,一直在光谱成像领域深度钻研和发展,始终致力于研发高性能、高可靠性的光谱成像相机,为科研院校提供更优的产品和服务。在《低空背景下无人机目标的光谱特征研究及目标检测应用》这篇论文中提到中达瑞和 LCTF 作为多…...

FFmpeg avformat_open_input函数分析
函数内部的总体流程如下: avformat_open_input 精简后的代码如下: int avformat_open_input(AVFormatContext **ps, const char *filename,ff_const59 AVInputFormat *fmt, AVDictionary **options) {AVFormatContext *s *ps;int i, ret 0;AVDictio…...