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

5 Repository 层接口

5 Repository 层接口

5.1 简介

1.何时写?

当你需要对 Elasticsearch (ES) 中的某个 “数据表”(称为 “索引”)进行增删改查(CRUD)时。需要写这个接口。即:当我的项目中有一个实体类(比如 UserFileDocument),并且我想把这个实体类的数据存到 ES 里,或者从 ES 里查询它的数据时。

2.怎么写?

创建一个接口,继承 ElasticsearchRepository<实体类名, 主键类型> 即可。

3.为什么这么写?

继承后,Spring Data ES 框架会自动帮你实现所有基础的 CRUD 方法,你不用写任何实现代码。

4.类比

相当于 SSM 中为一张表创建一个 Dao 接口。
  • SSM Dao -> 操作 MySQL 表
  • 这个接口 -> 操作 ES 索引
以3 搜索功能代码实现中的代码为例。
核心结论:
UserFileDocumentRepository 是 你手写的接口,但继承了 Spring Data Elasticsearch 框架提供的 ElasticsearchRepository 接口,因此无需手写实现类,就能直接获得 ES 文档的基础 CRUD 操作能力(框架自动生成实现)。
如果上面的东西可以看懂,就可以停止了,看不懂在继续看。

5.2 接口的 “手写部分”

你需要手动创建这个接口,并完成以下 3 件核心事情(仅需接口定义,无需写实现类):

1.手写接口本身

创建 UserFileDocumentRepository.java 文件,代码如下(这部分完全是你手写的):
package com.snapan.es.repository; // 你项目的包路径(手写)import com.snapan.es.entity.UserFileDocument; // 你项目的 ES 实体类(手写导入)
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; // 框架提供的接口(导入)// 你手写的接口,继承框架的 ElasticsearchRepository
public interface UserFileDocumentRepository extends ElasticsearchRepository<UserFileDocument, Long> {// 这里可以手写自定义查询方法(可选,基础 CRUD 无需写)
}

2.关键:继承框架的 ElasticsearchRepository

这是 “不用手写实现类” 的核心 ——你手写的接口继承了 Spring Data Elasticsearch 提供的通用接口,相当于 “借用” 了框架内置的基础 CRUD 方法。

3.指定泛型参数(手写)

继承时必须指定 2 个泛型(框架规定的规则,你需要正确填写):
  • 第一个泛型 UserFileDocument:你项目中对应的 ES 实体类(比如映射 ES 索引 user_file 的文档结构,类比 SSM 中 Dao 操作的 POJO);
  • 第二个泛型 Long:UserFileDocument 实体的主键类型(比如实体中 id 字段是 Long 类型,类比 SSM 中 POJO 的主键类型)。

5.3 框架提供的部分

你无需关心以下内容的实现,Spring Data Elasticsearch框架全自动化处理:

1.基础 CRUD 方法的实现

ElasticsearchRepository 接口内部已经定义了一套完整的 CRUD 方法(框架写好的),你的接口继承后,就自动拥有这些方法的实现。具体方法见5.4

2.动态代理生成实现类

Spring Boot 启动时,框架会通过 动态代理技术,在运行时自动生成 UserFileDocumentRepository 接口的实现类(你看不到 .class 文件),并将其注册为 Spring Bean,供 Service 层注入使用(类比 SSM 中 MyBatis 为 Dao 接口生成代理实现)。

5.4 ElasticsearchRepository 核心方法

ElasticsearchRepository 是 Spring Data Elasticsearch 提供的核心接口,定义了操作 ES 文档的通用方法。你的自定义 Repository 接口继承它后,即可直接调用这些方法,无需关心实现。
泛型说明:ElasticsearchRepository
  • T: 你要操作的 实体类(如 UserFileDocument)。
  • ID: 实体类中主键(@Id 标注的字段)的 数据类型(如 Long)。

1.创建(Create)与更新(Update)

方法签名
返回值类型
入参说明
功能说明
S save(S entity)
S
entity
: 要保存的实体对象
新增或更新
。如果实体的 ID 在 ES 中不存在,则执行新增;如果已存在,则执行全量更新(会覆盖原文档)。返回保存后的实体对象。
Iterable saveAll(Iterable entities)
Iterable
entities
: 实体对象的集合(如 List)
批量新增或更新
。对集合中的每个实体执行
save
操作。返回批量操作后的实体对象集合。
类比 SSM:save 对应 insert 或 update,saveAll 对应 batchInsert 或 batchUpdate。

2.读取(Read / Retrieve)

方法签名
返回值类型
入参说明
功能说明
Optional findById(ID id)
Optional
id
: 实体的主键 ID
根据 ID 查询单个实体。返回一个
Optional
对象,它可能包含查询到的实体(存在时),也可能为空(不存在时),用于避免空指针异常。
boolean existsById(ID id)
boolean
id
: 实体的主键 ID
判断具有指定 ID 的实体是否存在于 ES 中。存在返回
true
,否则返回
false
Iterable findAll()
Iterable
查询索引中的
所有
实体。返回一个可迭代的集合。
注意:数据量大时慎用
Iterable findAllById(Iterable ids)
Iterable
ids
: 主键 ID 的集合
根据一组 ID
批量查询
实体。返回包含所有找到实体的集合(未找到的 ID 会被忽略)。
Page findAll(Pageable pageable)
Page
pageable
: 分页参数(如
PageRequest.of(0, 10)
分页查询
所有实体。返回一个
Page
对象,包含了当前页的数据列表、总页数、总条数等分页信息。
long count()
long
统计索引中
所有
实体的总数量。
类比 SSM:findById 对应 selectById,findAll 对应 selectAll,count 对应 selectCount,Page 对应手动进行 limit 和 count(*) 查询。

3.删除(Delete)

方法签名
返回值类型
入参说明
功能说明
void deleteById(ID id)
void
id
: 实体的主键 ID
根据 ID
删除
单个实体。
void delete(T entity)
void
entity
: 要删除的实体对象
根据传入的实体对象(必须包含 ID)来删除 ES 中的对应文档。
void deleteAllById(Iterable ids)
void
ids
: 主键 ID 的集合
根据一组 ID
批量删除
实体。
void deleteAll(Iterable entities)
void
entities
: 要删除的实体对象集合
批量删除传入的实体对象集合。
void deleteAll()
void
删除索引中的所有文档
此操作不可逆,请极度谨慎使用!
它不会删除索引结构,只删除数据。
类比 SSM:deleteById 对应 deleteById,deleteAll 对应 deleteAll。

4.Spring Data 派生查询(Derived Query Methods)

除了继承来的方法,你还可以在 自己的接口 中直接声明遵循特定命名规则的方法,Spring Data ES 会自动为你生成实现。这是 Spring Data 最强大的特性之一。
概述
一个派生查询方法的名称,基本上遵循以下这个模式:
关键字 + 实体属性名 + 条件关键字 + (属性名)
  • 关键字 (Keyword):方法的前缀,用来表示你要做什么操作。
  • 实体属性名 (Property Name):你要查询的实体类中的字段名。注意:这里必须使用实体类的属性名,而不是 ES 索引中的字段名(如果两者不一致的话)。
  • 条件关键字 (Condition Keyword):用来限定查询的条件(如等于、大于、包含等)。
  • (属性名):如果条件需要一个值来比较(比如 “大于 100”),那么这个值就是方法的参数。
详细拆解与示例:
用 UserFileDocument 实体类来举例,假设它有以下属性:
  • Long id
  • String fileName
  • Long fileSize
  • Long userId
  • LocalDateTime uploadTime
1. 关键字 (Keyword)
最常用的关键字是 findBy。
  • findBy...:查询并返回符合条件的实体列表或单个实体。
  • existsBy...:查询是否存在符合条件的实体,返回 boolean。
  • countBy...:查询符合条件的实体总数,返回 long。
  • deleteBy...:删除符合条件的实体,返回 void 或删除的数量。
2. 条件关键字 (Condition Keyword) 详解
这是规则的核心,不同的条件关键字对应不同的查询逻辑。
条件关键字 (部分)
含义 (类比 SQL)
方法名示例
ES 查询含义 (简化)
(无,直接跟属性)
等于 (
=
)
findByFileName(String name)
fileName: "传入的name"
Is
等于 (
=
) (与上面等价,更清晰)
findByFileNameIs(String name)
fileName: "传入的name"
Not
不等于 (
!=
)
findByFileNameNot(String name)
fileName: { "not": "传入的name" }
Like
模糊匹配 (
LIKE
)
findByFileNameLike(String pattern)
fileName: "pattern"
(需自己加
%
,如
%test%
)
Containing
包含 (等价于
LIKE '%...%'
)
findByFileNameContaining(String keyword)
fileName: "*keyword*"
StartingWith
以... 开头 (
LIKE '...%'
)
findByFileNameStartingWith(String prefix)
fileName: "prefix*"
EndingWith
以... 结尾 (
LIKE '%...'
)
findByFileNameEndingWith(String suffix)
fileName: "*suffix"
GreaterThan
大于 (
>
)
findByFileSizeGreaterThan(long size)
fileSize: { "gt": size }
GreaterThanEqual
大于等于 (
>=
)
findByFileSizeGreaterThanEqual(long size)
fileSize: { "gte": size }
LessThan
小于 (
<
)
findByFileSizeLessThan(long size)
fileSize: { "lt": size }
LessThanEqual
小于等于 (
<=
)
findByFileSizeLessThanEqual(long size)
fileSize: { "lte": size }
Between
在... 之间 (
BETWEEN ... AND ...
)
findByFileSizeBetween(long min, long max)
fileSize: { "gte": min, "lte": max }
In
在集合中 (
IN (...)
)
findByUserIdIn(Collection userIds)
userId: { "in": [1, 2, 3] }
NotIn
不在集合中 (
NOT IN (...)
)
findByUserIdNotIn(Collection userIds)
userId: { "not": { "in": [1, 2, 3] } }
OrderBy...Asc
按... 升序排列
findByUserIdOrderByUploadTimeAsc(Long userId)
sort: { "uploadTime": "asc" }
OrderBy...Desc
按... 降序排列
findByUserIdOrderByUploadTimeDesc(Long userId)
sort: { "uploadTime": "desc" }
3. 组合查询 (多条件)
你可以使用 And 或 Or 来组合多个查询条件。
  • And:表示 “并且”,两个条件必须同时满足。
  • Or:表示 “或者”,两个条件满足一个即可。
示例:
  1. findByUserIdAndFileNameContaining(Long userId, String keyword)
  • 规则:findBy + UserId + And + FileName + Containing
  • 含义:查询 userId 等于给定值 并且 fileName 包含给定关键字的文档。
  1. findByFileSizeGreaterThanOrFileNameLike(long size, String pattern)
  • 规则:findBy + FileSize + GreaterThan + Or + FileName + Like
  • 含义:查询 fileSize 大于给定值 或者 fileName 匹配给定模式的文档。
4. 分页、排序和限制结果
这是让查询更强大的附加功能。
  • 分页:在方法的最后一个参数位置传入 Pageable 类型的对象。返回值通常使用 Page,它包含了数据列表、总页数、总条数等信息。
  • 示例:Page findByUserId(Long userId, Pageable pageable);
  • 调用:repository.findByUserId(1L, PageRequest.of(0, 10)); // 查询第 1 页,每页 10 条
  • 排序:有两种方式,一是在方法名中使用 OrderBy...Asc/Desc;二是在 Pageable 中指定排序规则。
  • 示例 (方法名):List findByUserIdOrderByUploadTimeDesc(Long userId);
  • 示例 (Pageable):repository.findByUserId(1L, PageRequest.of(0, 10, Sort.by("uploadTime").descending()));
  • 限制结果数量:可以在方法名中加入 First 或 Top 来限制返回结果的条数。
  • 示例:List findTop5ByUserIdOrderByUploadTimeDesc(Long userId);
  • 含义:查询 userId 为给定值的、按 uploadTime 降序排列的 前 5 条 记录。
应用示例
核心要点:
  • 属性名必须正确:方法名中的属性名必须和你的 UserFileDocument 类中的成员变量名完全一致(大小写敏感)。例如,fileName 不能写成 Filename。
  • 多单词属性:如果属性名是多个单词组成的(如 userName),在方法名中直接连写即可,Spring Data 会自动识别(这称为驼峰命名法)。
练习 1:我想查询 userId 为 100,并且 fileSize 大于 1024 的所有文件。
  • 关键字:findBy
  • 条件 1:UserId (等于)
  • 组合:And
  • 条件 2:FileSize + GreaterThan
  • 方法名:findByUserIdAndFileSizeGreaterThan(Long userId, long size);
练习 2:我想查询 fileName 以 "report_" 开头的,并且按 uploadTime 最新排序的前 10 条文件。
  • 关键字:findBy
  • 条件:FileName + StartingWith
  • 排序:OrderByUploadTimeDesc
  • 限制:Top10
  • 方法名:findTop10ByFileNameStartingWithOrderByUploadTimeDesc(String prefix);
练习 3:我想统计 userId 在 [1, 2, 3] 列表中的文件总数。
  • 关键字:countBy
  • 条件:UserId + In
  • 方法名:countByUserIdIn(Collection userIds);
只要你记住 findBy... + 属性名 + 条件 + And/Or + 属性名 + 条件 ... 这个模式,并结合上面的条件关键字表,你就可以构建出几乎所有你需要的查询方法,无需写一行 SQL 或 ES 查询 DSL。
http://www.dtcms.com/a/592735.html

相关文章:

  • 新乡网站优化平台id怎么打开wordpress
  • 小网站推荐会展官方网站建设
  • Springboot 启动过程及源码分析
  • STM32进行步进电机控制(PWM模式+翻转模式)
  • 信号系统常见的整体特性分类
  • PPT: Pre-trained Prompt Tuning - 预训练提示调优详解
  • 【RK3568】- 文件系统打包
  • 项目四:Dify智能开发与应用(零售企业基于Dify搭建会员智能运营平台)
  • 公司网站开发费计入什么科目迅当网络深圳外贸网站建设
  • 【C++11】右值引用+移动语义+完美转发
  • 商城系统的部署流程
  • 云朵课堂网站开发怎么收费装修公司口碑
  • python中numpy库学习笔记(2)
  • 【穿越Effective C++】条款16:成对使用new和delete时要采用相同形式——内存管理的精确匹配原则
  • 自己做的网站百度搜不到网站备案查询 工信部
  • 数据结构期中复习
  • TradingAgents-CN v1.0.0-preview 重磅发布!全新架构
  • 基于瑞萨 RA6M5 开发板的声源定位系统设计与实现
  • Vue 2 转 Vue 3, 差异不同点汇总, 快速上手vue3
  • 工业级环境传感器的网络通信与协议兼容性分析
  • 个人网站建设 免费下载一个公司备案两个网站
  • PR(1)11.10
  • 数据结构(19)
  • LWIP--以太网
  • 3分钟搞定,接口管理工具PostIn安装和配置
  • 【剑斩OFFER】算法的暴力美学——在排序数组中查找元素的第一个和最后一个位置
  • Agentic TASK01
  • 麒麟最新操作系统登录锁定配置
  • RLHF、DPO 算法
  • 网站排名优化课程网站建设公司华网天下官网