这篇文章是在看Spring Data Commons文档的时候梳理的内容,都是与Spring Data相关的,里面可能会涉及到Spring Data JPA的内容,但更多的是Commons的内容,Spring Data JPA只是一个具体的实现而已。
1. Spring Data 模块关系
Spring Data家族有多个模块:
- Spring Data JPA
- Spring Data Mongo
- …
但所有的模块都基于Spring Data Commoms
模块进行扩展。例如Spring Data JPA
是针对JPA做扩展的一个子模块;Spring Data Mongo
是针对MongoDB的子模块,但是共同的接口都是Spring Data。
可以说Spring Data Commons
是其所有子模块的抽象,定义了一系列的操作标准及接口。
2. 独立使用Spring Data
Spring Data
提供了RepositoryFactory
,可以独立于Spring容器之外使用:
RepositoryFactorySupport factory = … // Instantiate factory here
UserRepository repository = factory.getRepository(UserRepository.class);
3. Repository - dao - 存储仓库
在Spring Data
中,都是基于存储仓库Repository
对实体类对象进行CRUD
操作的。
其中,最核心的是Repository
接口,在org.springframework.data.repository
包中定义。
Repository
接口需要指定操作的实体类的类型
、实体类ID的类型
。在该接口中,是没有任何方法的,只是用于标记让Spring Data知道。
通常我们会使用CurdRepository
这个接口,当然,这个接口也是不包含JPA特性的,我们需要使用JPA特性的话,一般用的是JpaRepository
接口。
下面给出Spring Data JPA中,JpaRepository
的继承结构:
4. 使用指定Spring Data模块
上面一开始说了Spring Data有很多个不同的子模块,每个子模块对应一种数据存储方式或数据源,统称Spring Data *
吧。
要让Spring Data在运行的时候知道我们使用哪个模块,就要进行指定,指定模块的方法有两种:
存储库
使用Spring Data模块特定的接口
指定类型实体类
使用Spring Data模块模块特定的注解
指定类型
如果都不指定,在单模块的情形下是不存在问题的,但是如果项目中引入了不同的Spring Data模块,那么Spring Data在实际运行中就无法确定到底需要使用哪个模块。
5. 查询方法的拆分
Spring Data
以方法中的结构为findBy...
、deleteBy...
,其结构都是动词加上By
,By
是整个语句拆分的关键点。通常By
后面跟着的是查询的参数
列表,通过And
、Or
来连接。
在By
后面的参数中,首先将整个内容作为一个属性,如果找不到,然后再参数中以大写字母
为分割,直到找到对应的参数为止。
6. 分页查询、排序查询、限制查询、流式结果查询
6.1 排序查询
Spring Data
接受使用Sort
类型参数来进行排序查询的工作,Sort
主要有两个参数构成:
- 排序方向:ASC(升序)、DESC(降序)
- 排序字段
6.2 分页查询参数
Pageable
是Spring Data
提供出来进行分页查询参数输入的接口,里面主要定义多个与页面设定的方法:
实现有很多,最常用的是PageRequest
:
PageRequest
废弃了原本的new
方式来构建分页参数,建议使用类中提供的of(...)
静态方法来创建相关的分页参数实体。
of(...)
分页查询中允许带上排序字段
以及排序方向
两个参数,在源码中,这两个共同构建成了Sort
实体。这是很多业务中需要使用上的,首先需要讲内容进行排序,然后再分页列出。
分页查询中,next()
、previous()
返回的分别是下一页
、上一页
的分页参数实体,
6.3 分页查询结果(返回值)
除了支持常用的集合List
、Set
等查询结果集作为分页查询结果,Spring Data还有以下几种结果:
Page<T>
Slice<T>
List<T>
Set<T>
6.4 limit查询
在Mysql
中,我们需要获得前N
个结果,使用limit
关键字。
在Spring Data
中可以使用:
top
first
来进行限定最终的结果数,在top
、first
关键字后面可以加上数字表示最大结果大小,默认值为1
:
User findFirstByUsername(String username)
List<Article> findFirst10Bytitle(String title)
当然,这个是支持使用Pageable
、Sort
的。