当前位置: 首页 > news >正文

ElasticSearch - 基于 JavaRestClient 操作索引库和文档

目录

一、RestClient操作索引库

1.1、RestClient是什么?

1.2、JavaRestClient 实现创建、删除索引库

1.2.1、前言

1.2.1、初始化 JavaRestClient

1.2.2、创建索引库

1.2.3、判断索引库是否存在

1.2.4、删除索引库

1.3、JavaRestClient 实现文档的 CRUD

1.3.1、初始化 JavaRestClient 

1.3.2、添加文档(酒店数据)到索引库

1.3.3、根据 id 查询酒店数据

1.3.4、根据 id 修改酒店数据

1.3.5、根据 id 删除文档数据

1.3.6、批量导入文档


一、RestClient操作索引库


1.1、RestClient是什么?

前面我们已经了解了如何利用 DSL 语句去操作 es 的索引库和文档,但作为 java 程序员,将来肯定是要通过 java 代码去操作 es 的,那么想要实现这些,就需要通过 es 官方提供的 RestClient 实现.

RestClient 实际上就是 es 官方提供的各种语言的客户端,他的作用就是帮助我们组装 DSL 语句,然后发送 http 请求给 es 服务器,而我们只需要通过 java 代码将请求发送给客户端,然后客户端就会帮我们来处理剩下的这些事情.

官方文档地址:Elasticsearch Clients | Elastic

1.2、JavaRestClient 实现创建、删除索引库

1.2.1、前言

这里我将以一个 酒店 demo 工程来演示 JavaRestClient 的操作.

具体来讲,这是一个酒店的数据,创建的 sql 如下:

CREATE TABLE `tb_hotel` (`id` bigint(20) NOT NULL COMMENT '酒店id',`name` varchar(255) NOT NULL COMMENT '酒店名称;例:7天酒店',`address` varchar(255) NOT NULL COMMENT '酒店地址;例:航头路',`price` int(10) NOT NULL COMMENT '酒店价格;例:329',`score` int(2) NOT NULL COMMENT '酒店评分;例:45,就是4.5分',`brand` varchar(32) NOT NULL COMMENT '酒店品牌;例:如家',`city` varchar(32) NOT NULL COMMENT '所在城市;例:上海',`star_name` varchar(16) DEFAULT NULL COMMENT '酒店星级,从低到高分别是:1星到5星,1钻到5钻',`business` varchar(255) DEFAULT NULL COMMENT '商圈;例:虹桥',`latitude` varchar(32) NOT NULL COMMENT '纬度;例:31.2497',`longitude` varchar(32) NOT NULL COMMENT '经度;例:120.3925',`pic` varchar(255) DEFAULT NULL COMMENT '酒店图片;例:/img/1.jpg',PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

之后我们创建 索引库 的时候,就需要基于上述 sql 数据,来考虑 mapping 约束.

1.2.1、初始化 JavaRestClient

a)引入 es 的 RestHighLevelClient 依赖

        <dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId></dependency>

b)由于 SpringBoot 默认的 ES 版本是 7.6.2,因此这里我们需要覆盖默认的 ES 版本.

在 yml 配置文件中添加如下版本信息即可.

<properties><java.version>1.8</java.version>                    <elasticsearch.version>7.12.1</elasticsearch.version> 
</properties>

c)初始化 RestHighLevelClient.

这里我们创建一个测试类 HotelIndexTest ,用来演示 RestClient 操作的相关方法.

@SpringBootTest
class HotelIndexTest {private RestHighLevelClient client;@BeforeEachpublic void setUp() {client = new RestHighLevelClient(RestClient.builder(HttpHost.create("http//云服务器ip:9200")//将来如果是集群,这里还可以通过 HttpHost.create 继续连接多个节点));}@AfterEachpublic void tearDown() throws IOException {client.close();}}

1.2.2、创建索引库

这里就需要根据前面提供的表结构来考虑 mapping 该如何建立.

具体的要考虑:字段名、数据类型、是否参与搜索、是否分词、如果分词,分词器是什么?

这里可以先使用 Kibana 来编写.

PUT /hotel 
{"mappings": {"properties": {"id": { // id 按照数据库那边的定义,这里因该类型设置为 long// 但是这里比较特殊,在索引库中 id 比较特殊,将来都是字符串类型.// 又因为 id 将来不做分词处理,因此是 keyword 类型// id 将来肯定要参与 crud ,因此 index 就默认为 true 即可."type": "keyword"},"name": {// 酒店的名字需要搜索和分词."type": "text","analyzer": "ik_max_word", "copy_to": "all"},"address": {// 有时候我们需要根据地址来查询附近的酒店,分词也是有必要的("例如 徐汇龙华西路315弄58号")"type": "text","analyzer": "ik_max_word","copy_to": "all"},"price": {//将来要根据价格范围过滤酒店,所以需要搜索,分词就没必要了."type": "integer"},"score": {//这里就和 price 一样了"type": "integer"},"brand": {//酒店的品牌肯定是不需要分词了,但一定需要参与搜索."type": "keyword","copy_to": "all"},"city": {//城市名字不要分词,但需要参与搜索"type": "keyword","copy_to": "all"},"star_name": {//一星、二星、三星... 分词是没有意义的,组合起来才有意义.//有的人就想住5星酒店,那肯定要参与搜索."type": "keyword"},"business": {//商圈比如: 虹桥、外滩... 这些肯定不需要分词,但一定需要参与搜索."type": "keyword","copy_to": "all"},"pic": {//图片这里就是一个 url 路径,不需要分词,也没有人会搜这个 url//因此就这个 url 就可以当作关键字来处理."type": "keyword","index": false},"location": {//在 es 中有两种特殊的方式,专门来表示地理坐标//"geo_point": 表示地图上的点//"geo_shape": 表示地图上的区域,也就是多个点组成.//那么酒店肯定是属于一个点(毕竟从地球上看,再大的酒店也不过是点)// geo_point 里面由 经度 和 纬度 组成,并且是这两拼在一起组成的字符串"type": "geo_point"},"all": {// 将来 name、address、brand... 这些字段大概率都需要参与搜索// 也就意味着用户输入的的关键字,我们后端都需要根据多个字来搜.// 并且我们可以想象以下 es 作搜索的时候, 根据多个字段去搜索的效率肯定是要比一个字段搜索效率要低//这里对比以下数据库就清楚了.//最重要的是, 我们也希望用户输入名称就能搜到相关的内容, 用户输入品牌也能搜到相关内容...// es 就中有一个字段 "copy_to", 就是将当前字段的值拷贝到指定字段.//这里我们就将需要搜索的字段都拷贝到 all 这个字段中就 ok//这也就实现了在一个字段里, 搜索到多个字段的内容."type": "text","analyzer": "ik_max_word"}}}  
}

自定义 all 字段的解读: 

将来 name、address、brand... 这些字段大概率都需要参与搜索,也就意味着用户输入的的关键字,我们后端都需要根据多个字来搜,并且我们可以想象以下 es 作搜索的时候, 根据多个字段去搜索的效率肯定是要比一个字段搜索效率要低,这里对比以下数据库就清楚了~

最重要的是, 我们也希望用户输入名称就能搜到相关的内容, 用户输入品牌也能搜到相关内容... es 就中有一个字段 "copy_to", 就是将当前字段的值拷贝到指定字段。这里我们就将需要搜索的字段都拷贝到 all 这个字段中就 ok ,实现了在一个字段里, 搜索到多个字段的内容.

而且这里还做了优化,并不是真的吧文档拷贝进去,而是创建索引,将来你去查的时候,是看不到这些字段,但搜却能搜到(类似于根据指针找到数据所在位置).

创建索引库代码如下:

    @Testpublic void testCreateHotelIndex() throws IOException {//1.创建 Request 对象CreateIndexRequest request = new CreateIndexRequest("hotel");//2.编写请求参数(MAPPING_TEMPLATE 是一个静态常量,内容是创建索引库的 DSL 语句)request.source(MAPPING_TEMPLATE, XContentType.JSON);//3.发起请求client.indices().create(request, RequestOptions.DEFAULT);}
  • CreateIndexRequest 的构造参数就是请求创建的索引库的名字.
  • MAPPING_TEMPLATE:是自定义的静态常量,内容是创建索引库的 DSL 语句.
  • client.indices(): 这个方法的返回值是一个对象(indices 是 index 的复数形式),包含了操作索引库的所有方法.
  • RequestOptions.DEFAULT :就表示走默认的方法.

执行以后发现运行成功了~

之后去 Elastic DevTools 上去 GET,就可以看到新增的索引库了~

1.2.3、判断索引库是否存在

判断索引库是否存在代码如下:

    @Testpublic void testExistsHotelIndex() throws IOException {//1.创建 Request 对象GetIndexRequest request = new GetIndexRequest("hotel");//2.发送请求boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);System.out.println(exists);}

很多时候,我们先写 client.indices().exists 就可以之间看出需要什么参数

运行以后,可以看到通过了(true 是因为上个案例添加索引库是存在的).

1.2.4、删除索引库

判断删除索引库代码如下:

    @Testpublic void testDeleteHotelIndex() throws IOException {//1.创建 Request 对象DeleteIndexRequest request = new DeleteIndexRequest("hotel");//2.发送请求client.indices().delete(request, RequestOptions.DEFAULT);}

之后再查询就发现查询不到了,表明删除成功.

1.3、JavaRestClient 实现文档的 CRUD

1.3.1、初始化 JavaRestClient 

这里的初始化操作和操作索引库的初始化一样(本质上都是连接 JavaRestClient 客户端).

@SpringBootTest
class HotelDocumentTest {private RestHighLevelClient client;@BeforeEachpublic void setUp() {client = new RestHighLevelClient(RestClient.builder(HttpHost.create("http://云服务器ip:9200")));}@AfterEachpublic void tearDown() throws IOException {client.close();}}

1.3.2、添加文档(酒店数据)到索引库

Ps:操作文档前需要先创建对应索引库

这里我先通过 MyBatis-Puls 从数据库拿到数据,然后添加文档.

实体类如下(这里重写构造方法主要是为了 location 属性(地理位置),将经度,纬度合二为一):

@Data
@NoArgsConstructor
public class HotelDoc {private Long id;private String name;private String address;private Integer price;private Integer score;private String brand;private String city;private String starName;private String business;private String location;private String pic;public HotelDoc(Hotel hotel) {this.id = hotel.getId();this.name = hotel.getName();this.address = hotel.getAddress();this.price = hotel.getPrice();this.score = hotel.getScore();this.brand = hotel.getBrand();this.city = hotel.getCity();this.starName = hotel.getStarName();this.business = hotel.getBusiness();this.location = hotel.getLatitude() + ", " + hotel.getLongitude();this.pic = hotel.getPic();}
}

@NoArgsConstructor:生成无参构造.

编写添加文档代码:

    @Testpublic void testAddDocument() throws IOException {//1.获取酒店数据Hotel hotel = hotelService.getById(5865979L);//2.转化文档(主要是地理位置)HotelDoc hotelDoc = new HotelDoc(hotel);//3.转化为 JSON 格式String hotelJson = objectMapper.writeValueAsString(hotelDoc);//4.构造请求IndexRequest request = new IndexRequest("hotel").id(hotel.getId().toString());//5.添加请求参数(json 格式)request.source(hotelJson, XContentType.JSON);//6.发送请求client.index(request, RequestOptions.DEFAULT);}

运行后发现通过了

在 Kibana 上查询就可以得到对应的数据

1.3.3、根据 id 查询酒店数据

这里值得注意的是:通过 client.get 查询到的是一个 GetResponse 对象,需要获取里面的原数据.

代码如下:

    @Testpublic void testGetDocument() throws IOException {//1.构造请求GetRequest request = new GetRequest("hotel").id("5865979");//2.发送请求GetResponse response = client.get(request, RequestOptions.DEFAULT);//3.转化成jsonString json = response.getSourceAsString();System.out.println(json);}

运行后就可以得到对应的数据

1.3.4、根据 id 修改酒店数据

修改文档数据有两种方式(之前提到过):

  • 全量更新(就是上面演示的添加文档):再次写入 id 一样的文档,就会删除旧文档,添加新文档.
  • 局部更新(演示这个):只更新部分字段.
    @Testpublic void testUpdateDocument() throws IOException {//1.构造请求UpdateRequest request = new UpdateRequest("hotel", "5865979");//2.填写参数request.doc("name", "地表最强酒店","price", "99999");//3.发送请求client.update(request, RequestOptions.DEFAULT);}

在 Kibana 上通过 GET 查询如下:

1.3.5、根据 id 删除文档数据

删除文档代码如下:

    @Testpublic void testDeleteDocument() throws IOException {//1.构造请求DeleteRequest request = new DeleteRequest("hotel", "5865979");//2.发送请求client.delete(request, RequestOptions.DEFAULT);}

1.3.6、批量导入文档

例如导入酒店的所有数据,代码如下:

    @Testpublic void testBulkDocument() throws IOException {//1.获取酒店所有数据List<Hotel> hotelList = hotelService.list();//2.构造请求BulkRequest request = new BulkRequest();//3.准备参数for(Hotel hotel : hotelList) {//转化为文档(主要是地理位置)HotelDoc hotelDoc = new HotelDoc(hotel);String json = objectMapper.writeValueAsString(hotelDoc);request.add(new IndexRequest("hotel").id(hotel.getId().toString()).source(json, XContentType.JSON));}//4.发送请求client.bulk(request, RequestOptions.DEFAULT);}

运行后可以看到通过了

之后再 Kibana 上随机查询一个酒店数据都是存在的

相关文章:

ElasticSearch - 基于 JavaRestClient 操作索引库和文档

目录 一、RestClient操作索引库 1.1、RestClient是什么&#xff1f; 1.2、JavaRestClient 实现创建、删除索引库 1.2.1、前言 1.2.1、初始化 JavaRestClient 1.2.2、创建索引库 1.2.3、判断索引库是否存在 1.2.4、删除索引库 1.3、JavaRestClient 实现文档的 CRUD 1.3…...

【人脸质量评估】MagFace:一个既可以用作人脸识别,又可以用作人脸质量评估的方法

论文题目&#xff1a;《MagFace: A Universal Representation for Face Recognition and Quality Assessment》-CVPR2021 论文地址&#xff1a;https://arxiv.org/abs/2103.06627v4 代码地址&#xff1a;https://github.com/IrvingMeng/MagFace...

FPGA 图像缩放 千兆网 UDP 网络视频传输,基于RTL8211 PHY实现,提供工程和QT上位机源码加技术支持

目录 1、前言版本更新说明免责声明 2、相关方案推荐UDP视频传输--无缩放FPGA图像缩放方案我这里已有的以太网方案 3、设计思路框架视频源选择ADV7611 解码芯片配置及采集动态彩条跨时钟FIFO图像缩放模块详解设计框图代码框图2种插值算法的整合与选择 UDP协议栈UDP视频数据组包U…...

智能驾驶、智能家居、智能工业中的 AI 关键基础设施,半导体厂商恩智浦的角色是什么?

我们来看一条七年前的真实新闻报道&#xff0c;2016 年《福布斯》在报道中提到“2020 年会有 1000 万台的自动驾驶汽车”。然而 2023 年的现在&#xff0c;真正实现 L4 级别自动驾驶的汽车&#xff0c;仍然远远没有达到这个预测的数量。 另一边&#xff0c;数据显示&#xff0c…...

APScheduler包——python tornado框架中实现定时任务

介绍&#xff1a; APScheduler的全称是Advanced Python Scheduler。它是一个轻量级的 Python 定时任务调度框架。APScheduler 支持三种调度任务&#xff1a;固定时间间隔&#xff0c;固定时间点&#xff08;日期&#xff09;&#xff0c;Linux 下的 Crontab 命令。同时&#xf…...

BASH shell脚本篇3——字符串处理

这篇文章介绍下BASH shell中的字符串处理的相关命令。之前有介绍过shell的其它命令&#xff0c;请参考&#xff1a; BASH shell脚本篇1——基本命令 BASH shell脚本篇2——条件命令 Bash字符串也是一种数据类型&#xff0c;它用于表示文本而不是数字&#xff0c;它是一组可能…...

【SSL】用Certbot生成免费HTTPS证书

1. 实验背景 服务器&#xff1a;CentOS7.x 示例域名&#xff1a; www.example.com 域名对应的web站点目录&#xff1a; /usr/local/openresty/nginx/html 2. 安装docker # yum -y install yum-utils# yum-config-manager --add-repo https://download.docker.com/linux/ce…...

报错:java.sql.SQLSyntaxErrorException: Table ‘examsys.Teacher’ doesn’t exist

Linux大小写区分&#xff0c;导致部署项目时MySQL出现错误 问题原因&#xff1a;找不到Teacher这张表。因为在windows下的mysql表名不区分大小写&#xff0c;所以在windows下运行项目没问题。在linux中&#xff0c;mysql会区分大小写&#xff0c;所以sql语句表名用大写的就会找…...

.NET的PLC帮助类

TCP和UDP协议&#xff1a; TCP&#xff08;传输控制协议&#xff09;和UDP&#xff08;用户数据报协议&#xff09;是TCP/IP协议簇中的两种核心协议。它们在传输层上提供数据传输服务&#xff0c;但具有不同的特性和功能。 TCP协议是一种提供可靠、面向连接的字节流服务的传输协…...

Linux中nfs:failed: Operation not supported

先给出思路&#xff1a; 一个简单粗暴的方式&#xff1a;卸载重装排除未知问题&#xff0c;步骤如下&#xff1a; 一、在 Linux 上卸载 NFS 服务器&#xff0c;步骤&#xff1a; 停止 NFS 服务&#xff1a; sudo service nfs-kernel-server stop如果您使用的是不同的发行版&am…...

ElasticSearch映射与模板介绍

一、前言 前面有相关系列文章介绍了ES的基本概念和各种版本SDK的使用&#xff0c;ES现在已升级到8.5版本&#xff0c;有些概念和SDK用法都有很大变化&#xff0c;后续ES相关的文章会以8.3版本为基准介绍一些实际中应用需要掌握的概念以及一些比较实际的例子。 二、映射 ES环…...

通过 Azure 日志分析加强云安全

Microsoft Azure 云服务在安全日志存储、访问、可伸缩性、降低成本和易于部署方面提供了巨大的优势&#xff0c;因此在企业中很受欢迎。 Microsoft Azure 日志记录工具&#xff08;如 Log360&#xff09;可帮助管理 Azure 云基础结构中所有设备和应用程序&#xff08;如虚拟机…...

[H5动画制作系列 ]变量,帧频,监听器等的生命周期基础测试

模式:按照上述抓图,actions层&#xff0c;1帧,写初始化代码,10帧写返回代码到2帧代码,2-10帧之间一直循环。1帧及10帧代码如下&#xff1a; 如果程序在1-10之间循环,会反复创建变量i,多个监听器等。所以,第一帧最好执行一次即可&#xff0c;程序在2-10帧之间一直循环。...

基于SpringBoot的服装生产管理系统的设计与实现

目录 前言 一、技术栈 二、系统功能介绍 登录界面的实现 系统主界面的实现 用户管理模块的实现 人事安排管理模块的实现 工资管理模块的实现 考勤管理模块的实现 样板管理模块的实现 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 本协力服装厂服装生…...

动态内存操作(2)

接上一篇文章http://t.csdn.cn/1ONDq&#xff0c;这次我们继续讲解关于动态内存的相关知识。 一、常见的动态内存错误 1.对NULL指针进行解引用操作 #include<stdio.h> #include<stdlib.h> #include<limits.h> int main() {int* p (int*)malloc(INT_MAX/4);…...

Windows-Delphi 窗口置顶

露从今夜白&#xff0c;月是故乡明。 1.Delphi将窗口置顶 if topHwnd <> 0 thenbeginSetWindowPos(topHwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE);tmr1.Enabled : True;end; 其中topHwnd是目标窗口的句柄。 2.窗口取消置顶 if topHwnd <> 0 th…...

CVE-2020-11978 Apache Airflow 命令注入漏洞分析与利用

简介 漏洞软件&#xff1a;Apache Airflow影响版本&#xff1a;< 1.10.10 环境 Vulhub 漏洞测试靶场 复现步骤 进入 /root/vulhub/airflow/CVE-2020-11978/ 目录运行以下命令启动环境 # 初始化数据库 docker compose run airflow-init # 开启服务 docker compose up -…...

面试经典算法1:DFS

一、前言 1、题目描述和代码仅供参考&#xff0c;如果有问题欢迎指出 2、解题代码采用acm模式&#xff08;自己处理输入输出&#xff09;&#xff0c;不采用核心代码模式&#xff08;只编程核心函数&#xff09; 3、解题代码采用C语言&#xff08;ai一键翻译任意语言&#xff…...

Windows系统利用cpolar内网穿透搭建Zblog博客网站并实现公网访问内网!

文章目录 1. 前言2. Z-blog网站搭建2.1 XAMPP环境设置2.2 Z-blog安装2.3 Z-blog网页测试2.4 Cpolar安装和注册 3. 本地网页发布3.1. Cpolar云端设置3.2 Cpolar本地设置 4. 公网访问测试5. 结语 1. 前言 想要成为一个合格的技术宅或程序员&#xff0c;自己搭建网站制作网页是绕…...

SmartCode ViewerX VNC 3.11 Crack

SmartCode ViewerX VNC 查看器 ActiveX 轻松地将 VNC 查看器功能添加到您的应用程序中 SmartCode ViewerX VNC Viewer ActiveX 使开发人员可以使用一组直观的 ActiveX 属性和方法完全访问 VNC 查看器功能。借助ViewerX控件&#xff0c;开发人员可以轻松地为其应用程序提供屏幕共…...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…...

linux之kylin系统nginx的安装

一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源&#xff08;HTML/CSS/图片等&#xff09;&#xff0c;响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址&#xff0c;提高安全性 3.负载均衡服务器 支持多种策略分发流量…...

Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?

Golang 面试经典题&#xff1a;map 的 key 可以是什么类型&#xff1f;哪些不可以&#xff1f; 在 Golang 的面试中&#xff0c;map 类型的使用是一个常见的考点&#xff0c;其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

Admin.Net中的消息通信SignalR解释

定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...

Oracle查询表空间大小

1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

页面渲染流程与性能优化

页面渲染流程与性能优化详解&#xff08;完整版&#xff09; 一、现代浏览器渲染流程&#xff08;详细说明&#xff09; 1. 构建DOM树 浏览器接收到HTML文档后&#xff0c;会逐步解析并构建DOM&#xff08;Document Object Model&#xff09;树。具体过程如下&#xff1a; (…...

大模型多显卡多服务器并行计算方法与实践指南

一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...

Java + Spring Boot + Mybatis 实现批量插入

在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法&#xff1a;使用 MyBatis 的 <foreach> 标签和批处理模式&#xff08;ExecutorType.BATCH&#xff09;。 方法一&#xff1a;使用 XML 的 <foreach> 标签&#xff…...

【分享】推荐一些办公小工具

1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由&#xff1a;大部分的转换软件需要收费&#xff0c;要么功能不齐全&#xff0c;而开会员又用不了几次浪费钱&#xff0c;借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...

Java编程之桥接模式

定义 桥接模式&#xff08;Bridge Pattern&#xff09;属于结构型设计模式&#xff0c;它的核心意图是将抽象部分与实现部分分离&#xff0c;使它们可以独立地变化。这种模式通过组合关系来替代继承关系&#xff0c;从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...