news 2026/1/17 7:55:32

Spring Boot + Easy-ES 3.0 + Easyearch 实战:从 CRUD 到“避坑”指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Spring Boot + Easy-ES 3.0 + Easyearch 实战:从 CRUD 到“避坑”指南

unsetunset前言:unsetunset

在 Elasticsearch 的开发中,官方的 RestHighLevelClient 虽然强大,但代码冗余度高,构建复杂查询如同“拼积木”。

Easy-ES(简称 EE)作为 ES 界的“MyBatis-Plus”,凭借其强大的 ORM 能力和简洁的 API,正在成为许多 Java 开发者的首选。

昨晚用 Trae 编译器生成了一个 Demo,跑通是跑通了,但过程并非一帆风顺。

今天这篇文章,不讲虚的,直接复盘一套完整的Spring Boot + Easy-ES 3.0 实战,并重点拆解开发过程中遇到的Top 3 核心坑点

👉 欢迎加入小哈的星球,你将获得:专属的项目实战(多个项目) / 1v1 提问 /Java 学习路线 /学习打卡 / 每月赠书 / 社群讨论

  • 新项目:《Spring AI 项目实战》正在更新中..., 基于 Spring AI + Spring Boot 3.x + JDK 21;

  • 《从零手撸:仿小红书(微服务架构)》 已完结,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17..., 点击查看项目介绍;演示地址:http://116.62.199.48:7070/

  • 《从零手撸:前后端分离博客项目(全栈开发)》2期已完结,演示链接:http://116.62.199.48/;

  • 专栏阅读地址:https://www.quanxiaoha.com/column

截止目前,累计输出 100w+ 字,讲解图 4013+ 张,还在持续爆肝中..后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,Spring Cloud Alibaba 等等,戳我加入学习,解锁全部项目,已有4100+小伙伴加入

建议收藏,关键时刻能用得上。

unsetunset一、 环境准备:拒绝“依赖地狱”unsetunset

很多同学在接入 ES 时,第一步就倒在了 Maven 依赖冲突上。Easy-ES 3.0.0 虽然简化了配置,但对 ES 客户端版本的兼容性依然有要求。

1.1 技术栈清单

  • JDK: 8+ / 11 / 17 (推荐 17+),我用的 21版本。

  • Spring Boot: 2.7.18

  • Easy-ES: 3.0.0 (Dromara 社区出品)

  • Easyesarch: 2.0.0 (Easy-ES 3.0 也支持 8.x)

    Elasticsearch 国产化替代 ——信创政策到技术选型的全面指南调研报告 V1.0

1.2 核心 POM 配置(关键!)

避坑提示:不要只引入easy-es-boot-starter就觉得万事大吉了。如果你的 ES 服务端是 7.X,务必显式锁定elasticsearchelasticsearch-rest-high-level-client的版本,否则 Spring Boot 的默认版本可能会把你坑死。Easysearch 也可以兼容并使用如下的配置。

<dependencies> <dependency> <groupId>org.dromara.easy-es</groupId> <artifactId>easy-es-boot-starter</artifactId> <version>3.0.0</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch-rest-high-level-client</artifactId> <version>7.17.28</version> </dependency> <dependency> <groupId>org.elasticsearch</groupId> <artifactId>elasticsearch</artifactId> <version>7.17.28</version> </dependency> </dependencies>

1.3application.yml极简配置

easy-es: enable:true address:你的IP:9200 # 如果是生产环境,建议开启账号密码 username:admin password:your_password # 默认为 http,如果是 https 需显式声明 schema:https # 全局配置,生产环境建议关闭控制台打印 DSL,避免日志爆炸 global-config: print-dsl:true

unsetunset二、 极速 CRUD:像用 MyBatis-Plus 一样简单unsetunset

Easy-ES 最迷人的地方就在于此:零侵入,全注解

2.1 实体类定义

注意@IndexName注解,它定义了索引名称。EE 会自动处理驼峰转下划线。

@Data @IndexName("document_v1") // 建议加上版本号,方便后续通过别名迁移 public class Document { /** * ES 主键,推荐 String 类型 */ private String id; /** * 文档标题,analyzer 指定分词器(如 ik_max_word) */ @IndexField(fieldType = FieldType.TEXT, analyzer = "ik_max_word") private String title; /** * 文档内容 */ @IndexField(fieldType = FieldType.TEXT, analyzer = "ik_max_word") private String content; }

2.2 Mapper 接口

只需继承BaseEsMapper,无需写 XML,无需写实现类。

public interface DocumentMapper extends BaseEsMapper<Document> { // 你的自定义方法 }

unsetunset三、 实战避坑:踩过的 Top 3 深坑unsetunset

代码写完了,一运行测试用例,往往才是噩梦的开始。以下是三个最典型的错误场景及其原理分析。

3.1 坑点一:resource_already_exists_exception

  • 现象:单元测试第一次跑全是绿的,第二次跑直接红灯,报错index [...] already exists

  • 原理:ES 的索引(Index)相当于 MySQL 的表。MySQL 建表时如果不加IF NOT EXISTS也会报错。EE 提供了自动创建索引的功能,但测试环境往往需要“空杯心态”。

  • 解决方案:在@BeforeEach或测试开始前,先判断,后删除,再创建。

@Test @Order(1) public void testCreateIndex() { String indexName = "document_v1"; // 幂等性处理:存在则删,确保测试环境纯净 if (documentMapper.existsIndex(indexName)) { documentMapper.deleteIndex(indexName); } boolean success = documentMapper.createIndex(indexName); Assertions.assertTrue(success); }

3.2 坑点二:数据刚插入,查出来却是 Null?(核心!)

  • 现象:执行insert成功,马上执行select,结果查不到数据。

  • 原理(重点)ES 是近实时(Near Real-Time)搜索引擎,不是实时数据库

    • 数据写入 ES 后,先进入 Memory Buffer,默认每隔1秒(refresh_interval)才会刷写到 File System Cache 变为可被搜索(Searchable)。

    • 这就是为什么你插入成功了,但立刻查不到。

  • 解决方案

    • 测试环境:强制刷新。调用mapper.refresh()

    • 生产环境严禁频繁调用refresh()!这会导致产生大量的小 Segment 文件,严重拖慢写入性能并增加 Merge 压力。生产环境应容忍这 1 秒的延迟,或者通过业务逻辑规避(如先写库,UI 层做假反馈)。

@Test @Order(2) public void testInsertAndGet() { Document doc = new Document(); doc.setTitle("Easy-ES实战"); doc.setContent("铭毅天下风格博文"); documentMapper.insert(doc); // 【关键一步】测试环境下,强制刷新索引,让数据立即可见 documentMapper.refresh(); // 此时才能查到 Document result = documentMapper.selectById(doc.getId()); Assertions.assertNotNull(result); }

3.3 坑点三:中文乱码与各种控制台红字

  • 现象:Windows PowerShell 下跑 Maven 测试,日志里的中文全是乱码,根本看不懂报错信息。

  • 原因:Windows 终端默认 GBK,而 Maven 和 Java 都在用 UTF-8,编码不一致导致“鸡同鸭讲”。

  • 解决方案:不要改系统配置,直接让 Maven 听话。

pom.xml中强行指定 Surefire 插件编码:

<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration> <argLine>-Dfile.encoding=UTF-8</argLine> </configuration> </plugin>

unsetunset四、 完整实战代码(复制即用)unsetunset

为了让大家能直接上手,这里提供一份集成了 CRUD 和上述修复方案的完整测试用例。采用 JUnit 5 的@Order确保执行顺序。

@SpringBootTest @TestMethodOrder(MethodOrderer.OrderAnnotation.class) public class DocumentEsTest { @Autowired private DocumentMapper documentMapper; /** * 1. 初始化索引 */ @Test @Order(1) public void initIndex() { String indexName = "document_v1"; documentMapper.deleteIndex(indexName); // 暴力重置,仅限测试 documentMapper.createIndex(indexName); } /** * 2. 插入与查询 */ @Test @Order(2) public void testInsert() { Document doc = new Document(); doc.setTitle("Java性能优化"); doc.setContent("深入理解JVM与垃圾回收"); int success = documentMapper.insert(doc); Assertions.assertEquals(1, success); // 避坑:手动刷新 documentMapper.refresh(); // 链式查询体验 Document found = EsWrappers.lambdaChainQuery(documentMapper) .eq(Document::getTitle, "Java性能优化") .one(); System.out.println("查询结果:" + found); Assertions.assertNotNull(found); } /** * 3. 更新操作 */ @Test @Order(3) public void testUpdate() { // 构建更新条件 LambdaEsUpdateWrapper<Document> wrapper = new LambdaEsUpdateWrapper<>(); wrapper.eq(Document::getTitle, "Java性能优化") .set(Document::getContent, "内容已被更新:JVM实战"); documentMapper.update(null, wrapper); documentMapper.refresh(); // 再次刷新 Document updated = EsWrappers.lambdaChainQuery(documentMapper) .eq(Document::getTitle, "Java性能优化") .one(); Assertions.assertEquals("内容已被更新:JVM实战", updated.getContent()); } /** * 4. 删除操作 */ @Test @Order(4) public void testDelete() { LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>(); wrapper.eq(Document::getTitle, "Java性能优化"); documentMapper.delete(wrapper); documentMapper.refresh(); Long count = documentMapper.selectCount(wrapper); Assertions.assertEquals(0L, count); } }

unsetunset五、 总结与最佳实践unsetunset

Spring Boot 结合 Easy-ES 确实能极大地提升开发效率,把原本几百行的 ES 客户端代码缩减到寥寥数行。但在享受便利的同时,千万不要忽略了 Easysearch本身的特性

给开发者的 3 条建议:

  1. 版本匹配是红线:Easy-ES、Spring Boot、Easysearch 三者版本必须由 Pom 严格管控,切勿随意升级其中之一。

  2. 理解 Refresh 机制:不要在生产代码里滥用.refresh(),这无异于杀鸡取卵。如果业务对实时性要求极高(毫秒级),请反思 ES 是否是正确的存储选型,或者考虑 ID 查询。

  3. 拥抱 Wrapper:尽量使用 LambdaWrapper 构造查询,它能避免硬编码字段名(Magic String),在重构时非常安全。

👉 欢迎加入小哈的星球,你将获得:专属的项目实战(多个项目) / 1v1 提问 /Java 学习路线 /学习打卡 / 每月赠书 / 社群讨论

  • 新项目:《Spring AI 项目实战》正在更新中..., 基于 Spring AI + Spring Boot 3.x + JDK 21;

  • 《从零手撸:仿小红书(微服务架构)》 已完结,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17..., 点击查看项目介绍;演示地址:http://116.62.199.48:7070/

  • 《从零手撸:前后端分离博客项目(全栈开发)》2期已完结,演示链接:http://116.62.199.48/;

  • 专栏阅读地址:https://www.quanxiaoha.com/column

截止目前,累计输出 100w+ 字,讲解图 4013+ 张,还在持续爆肝中..后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,Spring Cloud Alibaba 等等,戳我加入学习,解锁全部项目,已有4100+小伙伴加入

1. 我的私密学习小圈子,从0到1手撸企业实战项目~ 2. 一款开源强大的数据同步神器,主流数据库全支持! 3. 提高系统吞吐量的一把利器:DeferredResult 到底有多强? 4. 新项目为什么更推荐WebFlux,而非SpringMVC?
最近面试BAT,整理一份面试资料《Java面试BATJ通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。 获取方式:点“在看”,关注公众号并回复 Java 领取,更多内容陆续奉上。
PS:因公众号平台更改了推送规则,如果不想错过内容,记得读完点一下“在看”,加个“星标”,这样每次新文章推送才会第一时间出现在你的订阅列表里。 点“在看”支持小哈呀,谢谢啦
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2025/12/16 11:19:15

商业赋能,全球共生!COSCon‘25 开源全球商业化论坛议程正式发布

中国开源年会 COSCon 是业界最具影响力的开源盛会之一&#xff0c;由开源社在 2015 年首次发起&#xff0c;2016 年正式得以命名。九年来&#xff0c;中国开源年会以其独特的中立社区定位及日益增加的影响力&#xff0c;吸引了越来越多国内外企业、高校、开源组织和社区的大力支…

作者头像 李华
网站建设 2026/1/16 13:58:53

SM3国密算法PHP实现终极指南:快速构建安全加密应用

SM3国密算法PHP实现终极指南&#xff1a;快速构建安全加密应用 【免费下载链接】SM3-PHP 国密标准SM3的PHP实现 项目地址: https://gitcode.com/gh_mirrors/sm3/SM3-PHP 在当今数据安全日益重要的时代&#xff0c;国产密码算法SM3凭借其强大的安全性能&#xff0c;正在成…

作者头像 李华
网站建设 2026/1/17 4:19:27

3步搭建专业级后台管理系统:Art Design Pro终极配置手册

3步搭建专业级后台管理系统&#xff1a;Art Design Pro终极配置手册 【免费下载链接】art-design-pro 这是一个基于 Vue3、TypeScript、Vite 和 Element-Plus 精心打造的后台管理系统模板&#xff0c;专注于用户体验和视觉设计。 项目地址: https://gitcode.com/GitHub_Trend…

作者头像 李华
网站建设 2025/12/16 11:19:02

D3.js标签防重叠实战:5步打造零冲突的专业级数据可视化

在数据可视化领域&#xff0c;标签重叠是影响图表可读性的主要问题。当密集的数据点标签相互遮挡时&#xff0c;再精美的设计也会失去价值。D3.js作为业界领先的可视化库&#xff0c;通过其强大的物理模拟引擎和智能算法&#xff0c;让标签自动避让变得简单高效。本文将带你从零…

作者头像 李华
网站建设 2025/12/16 11:18:53

Pts物理引擎实战:构建动态粒子系统的完整指南

Pts物理引擎实战&#xff1a;构建动态粒子系统的完整指南 【免费下载链接】pts A library for visualization and creative-coding 项目地址: https://gitcode.com/gh_mirrors/pt/pts 你是否曾想过在网页中创建逼真的物理效果&#xff0c;让粒子像真实世界一样相互碰撞、…

作者头像 李华
网站建设 2026/1/12 8:59:14

现代软件架构演进:从单体到云原生 + 代码实战详解

现代软件架构演进&#xff1a;从单体到云原生 代码实战详解目标读者&#xff1a;具备基础后端开发经验&#xff0c;希望深入理解架构落地细节的中高级开发者。一、单体架构&#xff1a;一个 Flask 单体应用示例 场景 我们构建一个简易电商系统&#xff0c;包含用户注册、商品浏…

作者头像 李华