Skip to content

Commit 6c87289

Browse files
committed
docs: 更新文档
1 parent aef9f85 commit 6c87289

File tree

8 files changed

+336
-18
lines changed

8 files changed

+336
-18
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@
6363
- [Spring 集成 Mybatis](docs/01.Java/13.框架/01.Spring/02.Spring数据/10.Spring集成Mybatis.md)
6464
- [Spring 访问 Redis](docs/01.Java/13.框架/01.Spring/02.Spring数据/21.Spring访问Redis.md)
6565
- [Spring 访问 MongoDB](docs/01.Java/13.框架/01.Spring/02.Spring数据/22.Spring访问MongoDB.md)
66-
- [SpringBoot 之 Elasticsearch](docs/01.Java/13.框架/01.Spring/02.Spring数据/24.SpringBoot之Elasticsearch.md)
66+
- [Spring 访问 Elasticsearch](docs/01.Java/13.框架/01.Spring/02.Spring数据/23.Spring访问Elasticsearch.md)
6767

6868
### Web
6969

docs/01.Java/13.框架/01.Spring/02.Spring数据/04.Spring之JPA.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,15 +58,15 @@ spring.datasource.url = jdbc:mysql://localhost:3306/spring_tutorial?serverTimezo
5858
spring.datasource.driver-class-name = com.mysql.cj.jdbc.Driver
5959
spring.datasource.username = root
6060
spring.datasource.password = root
61-
# 日志打印执行的SQL
61+
# 是否打印 JPA SQL 日志
6262
spring.jpa.show-sql = true
6363
# Hibernate的DDL策略
6464
spring.jpa.hibernate.ddl-auto = create-drop
6565
```
6666

6767
(4)定义实体
6868

69-
```
69+
```java
7070
import lombok.AllArgsConstructor;
7171
import lombok.Data;
7272
import lombok.NoArgsConstructor;
@@ -605,4 +605,4 @@ Spring Data 翻页查询总是返回 Page 对象,Page 对象提供了以下常
605605

606606
- [Spring 官网](https://spring.io/)
607607
- [Spring Framework 官方文档](https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/index.html)
608-
- [Spring Boot 官方文档](https://docs.spring.io/spring-boot/docs/current/reference/html/data.html)
608+
- [Spring Boot 官方文档](https://docs.spring.io/spring-boot/docs/current/reference/html/data.html)
Lines changed: 300 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,300 @@
1+
---
2+
title: Spring Data 综合
3+
date: 2023-02-08 09:10:35
4+
categories:
5+
- Java
6+
- 框架
7+
- Spring
8+
- Spring数据
9+
tags:
10+
- Java
11+
- 框架
12+
- Spring
13+
- SpringBoot
14+
permalink: /pages/191cdb/
15+
---
16+
17+
# Spring Data 综合
18+
19+
Spring Data Repository 抽象的目标是显著减少各种访问持久化存储的样板式代码。
20+
21+
## 核心概念
22+
23+
Repository 是 Spring Data 的核心接口。此接口主要用作标记接口,以捕获要使用的类型并帮助您发现扩展此接口的接口。`CrudRepository``ListCrudRepository` 接口为被管理的实体类提供复杂的 CRUD 功能。`ListCrudRepository` 提供等效方法,但它们返回 `List`,而 `CrudRepository` 方法返回 `Iterable`
24+
25+
`CrudRepository` 接口定义:
26+
27+
```java
28+
public interface CrudRepository<T, ID> extends Repository<T, ID> {
29+
30+
<S extends T> S save(S entity);
31+
32+
Optional<T> findById(ID primaryKey);
33+
34+
Iterable<T> findAll();
35+
36+
long count();
37+
38+
void delete(T entity);
39+
40+
boolean existsById(ID primaryKey);
41+
42+
// … more functionality omitted.
43+
}
44+
```
45+
46+
> Spring Data 项目也提供了一些特定持久化技术的抽象接口,如:JpaRepository 或 MongoRepository。这些接口扩展了 CrudRepository 并暴露了一些持久化技术的底层功能。
47+
48+
除了 `CrudRepository` 之外,还有一个 `PagingAndSortingRepository` 接口,它添加了额外的方法来简化对实体的分页访问:
49+
50+
```java
51+
public interface PagingAndSortingRepository<T, ID> {
52+
53+
Iterable<T> findAll(Sort sort);
54+
55+
Page<T> findAll(Pageable pageable);
56+
}
57+
```
58+
59+
【示例】要按页面大小 20 访问 User 的第二页,可以执行如下操作
60+
61+
```java
62+
PagingAndSortingRepository<User, Long> repository = // … get access to a bean
63+
Page<User> users = repository.findAll(PageRequest.of(1, 20));
64+
```
65+
66+
除了查询方法之外,计数和删除时的查询也是可用的。
67+
68+
【示例】根据姓氏计数
69+
70+
```java
71+
interface UserRepository extends CrudRepository<User, Long> {
72+
long countByLastname(String lastname);
73+
}
74+
```
75+
76+
【示例】根据姓氏删除
77+
78+
```java
79+
interface UserRepository extends CrudRepository<User, Long> {
80+
81+
long deleteByLastname(String lastname);
82+
83+
List<User> removeByLastname(String lastname);
84+
}
85+
```
86+
87+
## 查询方法
88+
89+
使用 Spring Data 对数据库进行查询有以下四步:
90+
91+
1. 声明一个扩展 `Repository` 或其子接口的接口,并指定泛型类型(实体类和 ID 类型),如以下示例所示:
92+
93+
```java
94+
interface PersonRepository extends Repository<Person, Long> { … }
95+
```
96+
97+
2. 在接口中声明查询方法
98+
99+
```java
100+
interface PersonRepository extends Repository<Person, Long> {
101+
List<Person> findByLastname(String lastname);
102+
}
103+
```
104+
105+
3. 使用 [JavaConfig](https://docs.spring.io/spring-data/jdbc/docs/current/reference/html/#repositories.create-instances.java-config)[XML 配置](https://docs.spring.io/spring-data/jdbc/docs/current/reference/html/#repositories.create-instances)为这些接口创建代理实例
106+
107+
```java
108+
@EnableJpaRepositories
109+
class Config { … }
110+
```
111+
112+
4. 注入 `Repository` 实例并使用
113+
114+
```java
115+
class SomeClient {
116+
117+
private final PersonRepository repository;
118+
119+
SomeClient(PersonRepository repository) {
120+
this.repository = repository;
121+
}
122+
123+
void doSomething() {
124+
List<Person> persons = repository.findByLastname("Matthews");
125+
}
126+
}
127+
```
128+
129+
## 定义 Repository
130+
131+
首先需要定义一个 Repository 接口,该接口必须扩展 Repository 并且指定泛型类型(实体类和 ID 类型)。如果想为该实体暴露 CRUD 方法,可以扩展 CrudRepository 接口。
132+
133+
### 微调 Repository 定义
134+
135+
Spring Data 提供了很多种 Repository 以应对不同的需求场景。
136+
137+
`CrudRepository` 提供了 CRUD 功能。
138+
139+
`ListCrudRepository``CrudRepository` 类似,但对于那些返回多个实体的方法,它返回一个 `List` 而不是 `Iterable`,这样使用可能更方便。
140+
141+
如果使用响应式框架,可以使用 `ReactiveCrudRepository``RxJava3CrudRepository`
142+
143+
`CoroutineCrudRepository` 支持 Kotlin 的协程特性。
144+
145+
`PagingAndSortingRepository` 提供了分页、排序功能。
146+
147+
如果不想扩展 Spring Data 接口,还可以使用 `@RepositoryDefinition` 注释您的 `Repository` 接口。 扩展一个 CRUD Repository 接口,需要暴露一组完整的方法来操作实体。如果希望对暴露的方法有选择性,可以将要暴露的方法从 CRUD Repository 复制到自定义的 Repository 中。 这样做时,可以更改方法的返回类型。 如果可能,Spring Data 将遵循返回类型。 例如,对于返回多个实体的方法,可以选择 `Iterable<T>``List<T>``Collection<T>``VAVR` 列表。
148+
149+
自定义基础 `Repository` 接口,必须用 `@NoRepositoryBean` 标记。 这可以防止 Spring Data 尝试直接创建它的实例并失败,因为它无法确定该 Repository 的实体,因为它仍然包含一个通用类型变量。
150+
151+
以下示例显示了如何有选择地暴露 CRUD 方法(在本例中为 findById 和 save):
152+
153+
```java
154+
@NoRepositoryBean
155+
interface MyBaseRepository<T, ID> extends Repository<T, ID> {
156+
157+
Optional<T> findById(ID id);
158+
159+
<S extends T> S save(S entity);
160+
}
161+
162+
interface UserRepository extends MyBaseRepository<User, Long> {
163+
User findByEmailAddress(EmailAddress emailAddress);
164+
}
165+
```
166+
167+
### 使用多个 Spring 数据模块
168+
169+
有时,程序中需要使用多个 Spring Data 模块。在这种情况下,必须区分持久化技术。当检测到类路径上有多个 Repository 工厂时,Spring Data 进入严格的配置模式。
170+
171+
如果定义的 Repository 扩展了特定模块中的 Repository,则它是特定 Spring Data 模块的有效候选者。
172+
173+
如果实体类使用了特定模块的类型注解,则它是特定 Spring Data 模块的有效候选者。 Spring Data 模块接受第三方注解(例如 JPA 的 `@Entity`)或提供自己的注解(例如用于 Spring Data MongoDB 和 Spring Data Elasticsearch 的 `@Document`)。
174+
175+
以下示例显示了一个使用模块特定接口(在本例中为 JPA)的 Repository:
176+
177+
```java
178+
interface MyRepository extends JpaRepository<User, Long> { }
179+
180+
@NoRepositoryBean
181+
interface MyBaseRepository<T, ID> extends JpaRepository<T, ID> { … }
182+
183+
interface UserRepository extends MyBaseRepository<User, Long> { … }
184+
```
185+
186+
MyRepository 和 UserRepository 扩展了 JpaRepository。它们是 Spring Data JPA 模块的有效候选者。
187+
188+
以下示例显示了一个使用通用接口的 Repository
189+
190+
```java
191+
interface AmbiguousRepository extends Repository<User, Long> { … }
192+
193+
@NoRepositoryBean
194+
interface MyBaseRepository<T, ID> extends CrudRepository<T, ID> { … }
195+
196+
interface AmbiguousUserRepository extends MyBaseRepository<User, Long> { … }
197+
```
198+
199+
AmbiguousRepository 和 AmbiguousUserRepository 仅扩展了 Repository 和 CrudRepository。 虽然这在使用唯一的 Spring Data 模块时很好,但是存在多个模块时,无法区分这些 Repository 应该绑定到哪个特定的 Spring Data。
200+
201+
以下示例显示了一个使用带注解的实体类的 Repository
202+
203+
```java
204+
interface PersonRepository extends Repository<Person, Long> { … }
205+
206+
@Entity
207+
class Person { … }
208+
209+
interface UserRepository extends Repository<User, Long> { … }
210+
211+
@Document
212+
class User { … }
213+
```
214+
215+
PersonRepository 引用 Person,它使用 JPA @Entity 注解进行标记,因此这个 Repository 显然属于 Spring Data JPA。 UserRepository 引用 User,它使用 Spring Data MongoDB 的 @Document 注解进行标记。
216+
217+
以下错误示例显示了一个使用带有混合注解的实体类的 Repository
218+
219+
```java
220+
interface JpaPersonRepository extends Repository<Person, Long> { … }
221+
222+
interface MongoDBPersonRepository extends Repository<Person, Long> { … }
223+
224+
@Entity
225+
@Document
226+
class Person { … }
227+
```
228+
229+
此示例中的实体类同时使用了 JPA 和 Spring Data MongoDB 的注解。示例中定义了两个 Repository:JpaPersonRepository 和 MongoDBPersonRepository。 一个用于 JPA,另一个用于 MongoDB。 Spring Data 不再能够区分 Repository,这会导致未定义的行为。
230+
231+
区分 Repository 的最后一种方法是确定 Repository 扫描 package 的范围。
232+
233+
```java
234+
@EnableJpaRepositories(basePackages = "com.acme.repositories.jpa")
235+
@EnableMongoRepositories(basePackages = "com.acme.repositories.mongo")
236+
class Configuration { … }
237+
```
238+
239+
## 定义查询方法
240+
241+
Repository 代理有两种方法可以从方法名称派生特定于存储的查询:
242+
243+
- 通过直接从方法名称派生查询。
244+
- 通过使用手动定义的查询。
245+
246+
可用选项取决于实际存储。但是,必须有一个策略来决定创建什么实际查询。
247+
248+
### 查询策略
249+
250+
以下策略可用于Repository 基础结构来解析查询。 对于 Java 配置,您可以使用 EnableJpaRepositories 注释的 queryLookupStrategy 属性。 特定数据存储可能不支持某些策略。
251+
252+
- `CREATE` 尝试从查询方法名称构造特定存储的查询。
253+
- `USE_DECLARED_QUERY` 尝试查找已声明的查询,如果找不到则抛出异常。
254+
- `CREATE_IF_NOT_FOUND` (默认)结合了 `CREATE``USE_DECLARED_QUERY`
255+
256+
### 查询创建
257+
258+
Spring Data 中有一套内置的查询构建器机制,可以自动映射符合命名和参数规则的方法。
259+
260+
```java
261+
interface PersonRepository extends Repository<Person, Long> {
262+
263+
List<Person> findByEmailAddressAndLastname(EmailAddress emailAddress, String lastname);
264+
265+
// Enables the distinct flag for the query
266+
List<Person> findDistinctPeopleByLastnameOrFirstname(String lastname, String firstname);
267+
List<Person> findPeopleDistinctByLastnameOrFirstname(String lastname, String firstname);
268+
269+
// Enabling ignoring case for an individual property
270+
List<Person> findByLastnameIgnoreCase(String lastname);
271+
// Enabling ignoring case for all suitable properties
272+
List<Person> findByLastnameAndFirstnameAllIgnoreCase(String lastname, String firstname);
273+
274+
// Enabling static ORDER BY for a query
275+
List<Person> findByLastnameOrderByFirstnameAsc(String lastname);
276+
List<Person> findByLastnameOrderByFirstnameDesc(String lastname);
277+
}
278+
```
279+
280+
解析查询方法名称分为主语和谓语。第一部分 (find…By, exists…By) 定义查询的主语,第二部分构成谓词。 主语可以包含更多的表达。 `find`(或其他引入关键字)和 `By` 之间的任何文本都被认为是描述性的,除非使用其中一个结果限制关键字,例如 `Distinct` 在要创建的查询上设置不同的标志或 `Top`/`First` 限制查询结果。
281+
282+
> 参考:
283+
>
284+
> [Spring Data 支持的查询主语关键词](https://docs.spring.io/spring-data/jdbc/docs/current/reference/html/#appendix.query.method.subject)
285+
>
286+
> [Spring Data 支持的查询谓语关键词](https://docs.spring.io/spring-data/jdbc/docs/current/reference/html/#appendix.query.method.predicate)
287+
288+
## 创建 Repository 实例
289+
290+
## 自定义 Repository 实现
291+
292+
## Spring Data 扩展
293+
294+
## 参考资料
295+
296+
- [Redis 官网](https://redis.io/)
297+
- [Redis Github](https://github.com/redis/redis)
298+
- [spring-data-redis Github](https://github.com/spring-projects/spring-data-redis)
299+
- [Spring Data Redis 官方文档](https://docs.spring.io/spring-data/redis/docs/current/reference/html/)
300+
- [Spring Data 官方示例](https://github.com/spring-projects/spring-data-examples/)

docs/01.Java/13.框架/01.Spring/02.Spring数据/21.Spring访问Redis.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
---
22
title: Spring 访问 Redis
3+
date: 2023-01-31 20:54:42
34
categories:
45
- Java
56
- 框架
@@ -11,6 +12,7 @@ tags:
1112
- Spring
1213
- SpringBoot
1314
- Redis
15+
permalink: /pages/65e4a2/
1416
---
1517

1618
# Spring 访问 Redis
@@ -242,4 +244,4 @@ public class RedisQuickstartTests {
242244
- [Redis Github](https://github.com/redis/redis)
243245
- [spring-data-redis Github](https://github.com/spring-projects/spring-data-redis)
244246
- [Spring Data Redis 官方文档](https://docs.spring.io/spring-data/redis/docs/current/reference/html/)
245-
- [Spring Data 官方示例](https://github.com/spring-projects/spring-data-examples/)
247+
- [Spring Data 官方示例](https://github.com/spring-projects/spring-data-examples/)

0 commit comments

Comments
 (0)