# 9.1. SQL数据库

Spring[框架](https://spring.io/projects/spring-framework)为使用 SQL 数据库提供了广泛的支持，从使用直接 JDBC 访问`JdbcClient`或`JdbcTemplate`完成“对象关系映射”技术（例如 Hibernate）。 [Spring Data](https://spring.io/projects/spring-data)提供了额外级别的功能：`Repository`直接从接口创建实现并使用约定从方法名称生成查询。

**9.1.1. 配置数据源**

Java 的`javax.sql.DataSource`接口提供了使用数据库连接的标准方法。传统上，`DataSource`使用 `URL`以及一些凭据来建立数据库连接。

> 请参阅[“操作方法”部分](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto.data-access.configure-custom-datasource)以获取更高级的示例，通常是为了完全控制数据源的配置。

**嵌入式数据库支持**

使用内存嵌入式数据库开发应用程序通常很方便。显然，内存数据库不提供持久存储。您需要在应用程序启动时填充数据库，并准备好在应用程序结束时丢弃数据。

> “操作方法”部分包括[有关如何初始化数据库的部分](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto.data-initialization)。

Spring Boot 可以自动配置嵌入式[H2](https://www.h2database.com/)、[HSQL](https://hsqldb.org/)和[Derby](https://db.apache.org/derby/)数据库。您无需提供任何连接 URL。您只需包含对要使用的嵌入式数据库的构建依赖项。如果类路径上有多个嵌入式数据库，请设置`spring.datasource.embedded-database-connection`配置属性来控制使用哪一个。将属性设置为`none`禁用嵌入式数据库的自动配置。

> 如果您在测试中使用此功能，您可能会注意到，无论您使用的应用程序上下文数量如何，整个测试套件都会重复使用同一个数据库。如果您想确保每个上下文都有一个单独的嵌入式数据库，您应该设置`spring.datasource.generate-unique-name`为`true`。

例如，典型的 POM 依赖关系如下：

```
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>org.hsqldb</groupId>
    <artifactId>hsqldb</artifactId>
    <scope>runtime</scope>
</dependency>
```

> 您需要依赖`spring-jdbc`嵌入式数据库才能自动配置。在此示例中，它是通过 `spring-boot-starter-data-jpa`传递地拉入的。
>
> 如果出于某种原因，您确实为嵌入式数据库配置了连接 URL，请注意确保禁用数据库的自动关闭功能。如果你使用H2，你应该设置`DB_CLOSE_ON_EXIT=FALSE`。如果您使用HSQLDB，您应该确保不使用`shutdown=true`。禁用数据库的自动关闭可以让 Spring Boot 控制数据库何时关闭，从而确保在不再需要访问数据库时关闭数据库。

**连接到生产数据库**

还可以使用池来自动配置生产数据库连接`DataSource`。

**数据源配置**

数据源配置由`spring.datasource.*`. 例如，您可以在`application.properties` 中声明以下部分：

```
spring.datasource.url=jdbc:mysql://localhost/test
spring.datasource.username=dbuser
spring.datasource.password=dbpass
```

> 您至少应该通过设置`spring.datasource.url`属性来指定 URL。否则，Spring Boot 会尝试自动配置嵌入式数据库
>
> Spring Boot 可以从 URL 推断出大多数数据库的 JDBC 驱动程序类。如果需要指定特定的类，可以使用该`spring.datasource.driver-class-name`属性。
>
> 为了创建池`DataSource`，我们需要能够验证有效的`Driver`类是否可用，因此我们在执行任何操作之前进行检查。换句话说，如果您设置了`spring.datasource.driver-class-name=com.mysql.jdbc.Driver`，那么该类必须是可加载的。

请参阅[`DataSourceProperties`](https://github.com/spring-projects/spring-boot/tree/v3.2.0/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceProperties.java)参考资料 了解更多支持的选项。这些是无论[实际实施](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#data.sql.datasource.connection-pool)如何都有效的标准选项。还可以通过使用各自的前缀（`spring.datasource.hikari.*` 、`spring.datasource.tomcat.*`、`spring.datasource.dbcp2.*`和`spring.datasource.oracleucp.*`）来微调特定于实现的设置。有关更多详细信息，请参阅您正在使用的连接池实现的文档。

例如，如果您使用[Tomcat 连接池](https://tomcat.apache.org/tomcat-10.1-doc/jdbc-pool.html#Common_Attributes)，则可以自定义许多其他设置，如以下示例所示：

```
spring.datasource.tomcat.max-wait=10000
spring.datasource.tomcat.max-active=50
spring.datasource.tomcat.test-on-borrow=true
```

如果没有可用连接，这会将池设置为在抛出异常之前等待 10000 毫秒，将最大连接数限制为 50，并在从池中借用连接之前验证连接。

**支持的连接池**

Spring Boot 使用以下算法来选择特定的实现：

1. 我们更喜欢[HikariCP](https://github.com/brettwooldridge/HikariCP)的性能和并发性。如果 HikariCP 可用，我们总是选择它。
2. 否则，如果 Tomcat 池`DataSource`可用，我们就使用它。
3. 否则，如果[Commons DBCP2](https://commons.apache.org/proper/commons-dbcp/)可用，我们将使用它。
4. 如果 HikariCP、Tomcat 和 DBCP2 都不可用，而 Oracle UCP 可用，则我们使用它。

> 如果您使用`spring-boot-starter-jdbc`或`spring-boot-starter-data-jpa`“starters”，您会自动获得对`HikariCP`.

您可以完全绕过该算法并通过设置`spring.datasource.type`属性来指定要使用的连接池。如果您在 Tomcat 容器中运行应用程序，这一点尤其重要，因为默认提供 `tomcat-jdbc`。

始终可以使用`DataSourceBuilder`添加任何连接池. 如果您定义自己的`DataSource`bean，则不会发生自动配置。`DataSourceBuilder`支持以下连接池：

* HikariCP
* Tomcat 池化`Datasource`
* Commons DBCP2
* Oracle UCP 和`OracleDataSource`
* Spring框架的`SimpleDriverDataSource`
* H2`JdbcDataSource`
* PostgreSQL`PGSimpleDataSource`
* C3P0

**连接到 JNDI 数据源**

如果将 Spring Boot 应用程序部署到应用程序服务器，您可能希望使用应用程序服务器的内置功能来配置和管理数据源，并使用 JNDI 访问它。

`spring.datasource.jndi-name`属性可用作`spring.datasource.url`、`spring.datasource.username`和`spring.datasource.password`属性的替代，以从特定 JNDI 位置访问`DataSource`。例如，以下部分`application.properties`显示了如何访问 JBoss AS 定义的`DataSource`：

```
spring.datasource.jndi-name=java:jboss/datasources/customers
```

**9.1.2. 使用 JdbcTemplate**

Spring`JdbcTemplate`和`NamedParameterJdbcTemplate`类是自动配置的，您可以使用`@Autowire`将它们直接添加到您自己的 bean 中，如以下示例所示：

```
@Component
public class MyBean {
​
    private final JdbcTemplate jdbcTemplate;
​
    public MyBean(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }
​
    public void doSomething() {
        this.jdbcTemplate ...
    }
​
}
```

您可以通过属性来自定义模板的一些属性`spring.jdbc.template.*`，如下例所示：

```
spring.jdbc.template.max-rows=500
```

> `NamedParameterJdbcTemplate` 在幕后重用相同的`JdbcTemplate` 实例。如果定义了多个`JdbcTemplate`并且不存在主要候选者，则不会自动配置 `NamedParameterJdbcTemplate`。

**9.1.3. 使用 JdbcClient**

Spring`JdbcClient`是根据`NamedParameterJdbcTemplate`自动配置的. 您也可以将其直接注入到您自己的 bean 中，如以下示例所示：

```
@Component
public class MyBean {
​
    private final JdbcClient jdbcClient;
​
    public MyBean(JdbcClient jdbcClient) {
        this.jdbcClient = jdbcClient;
    }
​
    public void doSomething() {
        this.jdbcClient ...
    }
​
}
```

如果您依靠自动配置来创建底层 JdbcTemplate，则客户端也会考虑使用 `spring.jdbc.template.*`属性的任何自定义。

**9.1.4. JPA 和 Spring Data JPA**

Java Persistence API 是一种标准技术，可让您将对象“映射”到关系数据库。`spring-boot-starter-data-jpa`POM提供了一种快速入门方法。它提供了以下关键依赖项：

* Hibernate：最流行的 JPA 实现之一。
* Spring Data JPA：帮助您实现基于 JPA 的存储库。
* Spring ORM：Spring 框架的核心 ORM 支持。

> 我们在这里不过多讨论 JPA 或[Spring Data](https://spring.io/projects/spring-data)的细节。您可以遵循[spring.io中的](https://spring.io/)[“使用 JPA 访问数据”](https://spring.io/guides/gs/accessing-data-jpa/)指南并阅读[Spring Data JPA](https://spring.io/projects/spring-data-jpa)和[Hibernate](https://hibernate.org/orm/documentation/)参考文档。

**实体类**

传统上，JPA“实体”类是在`persistence.xml`文件中指定的。对于 Spring Boot，这个文件不是必需的，而是使用“Entity Scanning”。默认情况下会扫描[自动配置包。](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#using.auto-configuration.packages)

任何用`@Entity`、`@Embeddable`、 或`@MappedSuperclass`注解的类都会被考虑。典型的实体类类似于以下示例：

```
@Entity
public class City implements Serializable {
​
    @Id
    @GeneratedValue
    private Long id;
​
    @Column(nullable = false)
    private String name;
​
    @Column(nullable = false)
    private String state;
​
    // ... additional members, often include @OneToMany mappings
​
    protected City() {
        // no-args constructor required by JPA spec
        // this one is protected since it should not be used directly
    }
​
    public City(String name, String state) {
        this.name = name;
        this.state = state;
    }
​
    public String getName() {
        return this.name;
    }
​
    public String getState() {
        return this.state;
    }
​
    // ... etc
​
}
```

> 您可以使用`@EntityScan`注释自定义实体扫描位置。请参阅“[从 Spring 配置中分离 @Entity 定义](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto.data-access.separate-entity-definitions-from-spring-configuration)”操作方法。

**Spring Data JPA 存储库**

[Spring Data JPA](https://spring.io/projects/spring-data-jpa)存储库是您可以定义来访问数据的接口。JPA 查询是根据您的方法名称自动创建的。例如，`CityRepository`接口可能声明一个`findAllByState(String state)`方法来查找给定州的所有城市。

对于更复杂的查询，您可以使用 Spring Data 的[`Query`](https://docs.spring.io/spring-data/jpa/docs/3.2.0/api/org/springframework/data/jpa/repository/Query.html)注释来注释您的方法。

Spring Data 存储库通常从[`Repository`](https://docs.spring.io/spring-data/commons/docs/3.2.0/api/org/springframework/data/repository/Repository.html)或[`CrudRepository`](https://docs.spring.io/spring-data/commons/docs/3.2.0/api/org/springframework/data/repository/CrudRepository.html)接口扩展。如果您使用自动配置，则会[在自动配置包中](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#using.auto-configuration.packages)搜索存储库。

> 您可以使用 `@EnableJpaRepositories`自定义位置来查找存储库。

以下示例显示了典型的 Spring Data 存储库接口定义：

```
public interface CityRepository extends Repository<City, Long> {
​
    Page<City> findAll(Pageable pageable);
​
    City findByNameAndStateAllIgnoringCase(String name, String state);
​
}
```

Spring Data JPA 存储库支持三种不同的引导模式：默认、延迟和懒加载。要启用延迟或懒加载引导，请分别将该`spring.data.jpa.repositories.bootstrap-mode`属性设置为`deferred`或`lazy`。当使用延迟或惰性引导时，自动配置`EntityManagerFactoryBuilder`将使用上下文`AsyncTaskExecutor`（如果有）作为引导执行器。如果存在多个，则将使用`applicationTaskExecutor`指定的那个。

> 使用延迟或惰性引导时，请确保在应用程序上下文引导阶段之后延迟对 JPA 基础结构的任何访问。您可以使用它`SmartInitializingSingleton`来调用任何需要 JPA 基础结构的初始化。对于作为 Spring bean 创建的 JPA 组件（例如转换器），请使用`ObjectProvider`延迟解析依赖项（如果有）。
>
> 我们仅仅触及了 Spring Data JPA 的皮毛。有关完整的详细信息，请参阅[Spring Data JPA 参考文档](https://docs.spring.io/spring-data/jpa/reference/3.2.0/)。

**Spring Data Envers 存储库**

如果[Spring Data Envers](https://spring.io/projects/spring-data-envers)可用，JPA 存储库会自动配置为支持典型的 Envers 查询。

要使用 Spring Data Envers，请确保您的存储库扩展`RevisionRepository`如同以下示例：

```
public interface CountryRepository extends RevisionRepository<Country, Long, Integer>, Repository<Country, Long> {
​
    Page<Country> findAll(Pageable pageable);
​
}
```

> 有关更多详细信息，请查看[Spring Data Envers 参考文档](https://docs.spring.io/spring-data/jpa/reference/3.2.0/#envers)。

**创建和删除 JPA 数据库**

默认情况下，仅当您使用嵌入式数据库（H2、HSQL 或 Derby）时才会自动创建 JPA 数据库。您可以使用`spring.jpa.*`属性显式配置 JPA 设置。例如，要创建和删除表，您可以将以下行添加到您的`application.properties`：

```
spring.jpa.hibernate.ddl-auto=create-drop
```

> Hibernate 自己的内部属性名称（如果您记得更好的话）是`hibernate.hbm2ddl.auto`。您可以通过使用`spring.jpa.properties.*`（在将它们添加到实体管理器之前删除前缀）来设置它以及其他 Hibernate 本机属性。以下行显示了为 Hibernate 设置 JPA 属性的示例：

```
spring.jpa.properties.hibernate[globally_quoted_identifiers]=true
```

前面示例中的行将`hibernate.globally_quoted_identifiers`属性的`true`值传递给Hibernate 实体管理器。

默认情况下，DDL 执行（或验证）被推迟到`ApplicationContext`开始为止。还有一个`spring.jpa.generate-ddl`标志，但如果 Hibernate 自动配置处于活动状态，则不会使用它，因为`ddl-auto`设置了更细粒度。

**在视图中打开EntityManager**

如果您正在运行 Web 应用程序，Spring Boot 默认情况下会注册[`OpenEntityManagerInViewInterceptor`](https://docs.spring.io/spring-framework/docs/6.1.1/javadoc-api/org/springframework/orm/jpa/support/OpenEntityManagerInViewInterceptor.html)以应用“在视图中打开 EntityManager”模式，以允许在 Web 视图中延迟加载。如果您不希望出现这种行为，您应该在您的`application.properties`将`spring.jpa.open-in-view`设置为`false`.

**9.1.5. Spring Data JDBC**

Spring Data 包括对 JDBC 的存储库支持，并将自动为`CrudRepository`. 对于更高级的查询，提供了`@Query`注释。

当类路径上有必要的依赖项时，Spring Boot 将自动配置 Spring Data 的 JDBC 存储库。可以将它们添加到您的项目中，并仅依赖于`spring-boot-starter-data-jdbc`. 如有必要，您可以通过向应用程序添加`@EnableJdbcRepositories`注释或`AbstractJdbcConfiguration`子类来控制 Spring Data JDBC 的配置。

> 有关 Spring Data JDBC 的完整详细信息，请参阅[参考文档](https://docs.spring.io/spring-data/jdbc/docs/3.2.0/reference/html/)。

**9.1.6. 使用 H2 的 Web 控制台**

[H2 数据库](https://www.h2database.com/)提供了一个[基于浏览器的控制台](https://www.h2database.com/html/quickstart.html#h2_console)，Spring Boot 可以为您自动配置。当满足以下条件时，控制台会自动配置：

* 您正在开发一个基于 servlet 的 Web 应用程序。
* 位于类路径上的`com.h2database:h2`。
* 您正在使用[Spring Boot 的开发者工具](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#using.devtools)。

> 如果您不使用 Spring Boot 的开发人员工具，但仍想使用 H2 的控制台，则可以将`spring.h2.console.enabled`属性配置为`true`。
>
> H2 控制台仅供开发期间使用，因此您应注意确保在生产中`spring.h2.console.enabled`未将其设置为`true`。

**更改 H2 控制台的路径**

默认情况下，控制台位于`/h2-console`。您可以使用`spring.h2.console.path`属性自定义控制台的路径。

**在安全应用程序中访问 H2 控制台**

H2 Console 使用框架，仅用于开发，没有实施 CSRF 保护措施。如果您的应用程序使用 Spring Security，则需要将其配置为

* 对针对控制台的请求禁用 CSRF 保护，
* 将标头设置`X-Frame-Options`为`SAMEORIGIN`来自控制台的响应。

有关[CSRF](https://docs.spring.io/spring-security/reference/6.2/features/exploits/csrf.html)和标头[X-Frame-Options 的](https://docs.spring.io/spring-security/reference/6.2/features/exploits/headers.html#headers-frame-options)更多信息可以在 Spring Security 参考指南中找到。

在简单的设置中，可以使用如下所示的`SecurityFilterChain`内容：

```
@Profile("dev")
@Configuration(proxyBeanMethods = false)
public class DevProfileSecurityConfiguration {
​
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    SecurityFilterChain h2ConsoleSecurityFilterChain(HttpSecurity http) throws Exception {
        http.securityMatcher(PathRequest.toH2Console());
        http.authorizeHttpRequests(yourCustomAuthorization());
        http.csrf((csrf) -> csrf.disable());
        http.headers((headers) -> headers.frameOptions((frame) -> frame.sameOrigin()));
        return http.build();
    }
​
​
}
```

> H2 控制台仅供开发期间使用。在生产中，禁用 CSRF 保护或允许网站使用框架可能会带来严重的安全风险。
>
> 当控制台的路径已自定义时，`PathRequest.toH2Console()`也会返回正确的请求匹配器。

**9.1.7. 使用 jOOQ**

jOOQ 面向对象查询 ( [jOOQ ) 是](https://www.jooq.org/)[Data Geekery](https://www.datageekery.com/)的一款流行产品，它从数据库生成 Java 代码，并允许您通过其流畅的 API 构建类型安全的 SQL 查询。商业版和开源版都可以与 Spring Boot 一起使用。

**代码生成**

为了使用 jOOQ 类型安全查询，您需要从数据库模式生成 Java 类。[您可以按照jOOQ 用户手册](https://www.jooq.org/doc/3.18.7/manual-single-page/#jooq-in-7-steps-step3)中的说明进行操作。如果您使用`jooq-codegen-maven`插件并且还使用“父 POM”`spring-boot-starter-parent`，则可以安全地省略该插件的`<version>`标签。您还可以使用 Spring Boot 定义的版本变量（例如`h2.version`）来声明插件的数据库依赖项。以下清单显示了一个示例：

```
<plugin>
    <groupId>org.jooq</groupId>
    <artifactId>jooq-codegen-maven</artifactId>
    <executions>
        ...
    </executions>
    <dependencies>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <version>${h2.version}</version>
        </dependency>
    </dependencies>
    <configuration>
        <jdbc>
            <driver>org.h2.Driver</driver>
            <url>jdbc:h2:~/yourdatabase</url>
        </jdbc>
        <generator>
            ...
        </generator>
    </configuration>
</plugin>
```

**使用 DSLContext**

jOOQ提供的Fluent API是通过`org.jooq.DSLContext`接口发起的。Spring Boot 自动将 `DSLContext` 配置为 Spring Bean 并将其连接到您应用程序的`DataSource`。要使用`DSLContext`，您可以注入它，如以下示例所示：

```
@Component
public class MyBean {
​
    private final DSLContext create;
​
    public MyBean(DSLContext dslContext) {
        this.create = dslContext;
    }
​
​
}
```

> jOOQ 手册倾向于使用名为`create`的变量来保存`DSLContext`.

然后，您可以使用`DSLContext`来构建查询，如以下示例所示：

```
public List<GregorianCalendar> authorsBornAfter1980() {
    return this.create.selectFrom(AUTHOR)
        .where(AUTHOR.DATE_OF_BIRTH.greaterThan(new GregorianCalendar(1980, 0, 1)))
        .fetch(AUTHOR.DATE_OF_BIRTH);
```

**jOOQ SQL 方言**

除非已配置`spring.jooq.sql-dialect`属性，否则 Spring Boot 会确定用于数据源的 SQL 方言。如果 Spring Boot 无法检测到方言，它会使用`DEFAULT`.

> Spring Boot 只能自动配置开源版本 jOOQ 支持的方言。

**定制jOOQ**

可以通过定义您自己的`DefaultConfigurationCustomizer`bean 来实现更高级的自定义，该 bean 将在创建`org.jooq.Configuration` `@Bean`时调用. 这优先于自动配置应用的任何内容。

如果您想完全控制 jOOQ 配置，您也可以创建自己的`org.jooq.Configuration` `@Bean`。

**9.1.8. 使用 R2DBC**

反应式关系数据库连接 ( [R2DBC](https://r2dbc.io/) ) 项目为关系数据库带来了反应式编程 API。R2DBC的`io.r2dbc.spi.Connection`提供了一种使用非阻塞数据库连接的标准方法。连接是通过使用`ConnectionFactory`提供的，类似于jdbc 中的 `DataSource`。

`ConnectionFactory`配置由 `spring.r2dbc.*`中的外部配置属性控制。例如，您可以在`application.properties` 中声明以下部分：

```
spring.r2dbc.url=r2dbc:postgresql://localhost/test
spring.r2dbc.username=dbuser
spring.r2dbc.password=dbpass
```

> 您不需要指定驱动程序类名，因为 Spring Boot 从 R2DBC 的连接工厂发现中获取驱动程序。
>
> 至少应该提供网址。URL 中指定的信息优先于各个属性，即`name`、`username`和`password`池选项。
>
> “操作方法”部分包括[有关如何初始化数据库的部分](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto.data-initialization.using-basic-sql-scripts)。

要自定义由`ConnectionFactory` 所创建的连接，即设置您不想（或无法）在中央数据库配置中配置的特定参数，您可以使用`ConnectionFactoryOptionsBuilderCustomizer` `@Bean`. 以下示例显示如何手动覆盖数据库端口，而其余选项则取自应用程序配置：

```
@Configuration(proxyBeanMethods = false)
public class MyR2dbcConfiguration {
​
    @Bean
    public ConnectionFactoryOptionsBuilderCustomizer connectionFactoryPortCustomizer() {
        return (builder) -> builder.option(ConnectionFactoryOptions.PORT, 5432);
    }
​
}
```

以下示例显示如何设置一些 PostgreSQL 连接选项：

```
@Configuration(proxyBeanMethods = false)
public class MyPostgresR2dbcConfiguration {
​
    @Bean
    public ConnectionFactoryOptionsBuilderCustomizer postgresCustomizer() {
        Map<String, String> options = new HashMap<>();
        options.put("lock_timeout", "30s");
        options.put("statement_timeout", "60s");
        return (builder) -> builder.option(PostgresqlConnectionFactoryProvider.OPTIONS, options);
    }
​
}
```

当`ConnectionFactory`bean 可用时，常规 JDBC`DataSource`自动配置就会停止。如果您想保留 JDBC`DataSource`自动配置，并且愿意接受在反应式应用程序中使用阻塞 JDBC API 的风险，请在应用程序中的一个`@Configuration`类添加`@Import(DataSourceAutoConfiguration.class)`以重新启用它。

**嵌入式数据库支持**

与[JDBC 支持](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#data.sql.datasource.embedded)类似，Spring Boot 可以自动配置嵌入式数据库以进行反应式使用。您无需提供任何连接 URL。您只需包含对要使用的嵌入式数据库的构建依赖项，如以下示例所示：

```
<dependency>
    <groupId>io.r2dbc</groupId>
    <artifactId>r2dbc-h2</artifactId>
    <scope>runtime</scope>
</dependency>
```

> 如果您在测试中使用此功能，您可能会注意到，无论您使用的应用程序上下文数量如何，整个测试套件都会重复使用同一个数据库。如果您想确保每个上下文都有一个单独的嵌入式数据库，您应该设置`spring.r2dbc.generate-unique-name`为`true`。

**使用数据库客户端**

`DatabaseClient` bean是自动配置的，您可以将`@Autowire`其直接添加到您自己的 bean 中，如以下示例所示：

```
@Component
public class MyBean {
​
    private final DatabaseClient databaseClient;
​
    public MyBean(DatabaseClient databaseClient) {
        this.databaseClient = databaseClient;
    }
​
    // ...
​
}
```

**Spring Data R2DBC 存储库**

[Spring Data R2DBC](https://spring.io/projects/spring-data-r2dbc)存储库是您可以定义来访问数据的接口。查询是根据您的方法名称自动创建的。例如，`CityRepository`接口可能声明一个`findAllByState(String state)`方法来查找给定州下的所有城市。

对于更复杂的查询，您可以使用 Spring Data 的[`Query`](https://docs.spring.io/spring-data/r2dbc/docs/3.2.0/api/org/springframework/data/r2dbc/repository/Query.html)注释来注释您的方法。

Spring Data 存储库通常从[`Repository`](https://docs.spring.io/spring-data/commons/docs/3.2.0/api/org/springframework/data/repository/Repository.html)或[`CrudRepository`](https://docs.spring.io/spring-data/commons/docs/3.2.0/api/org/springframework/data/repository/CrudRepository.html)接口扩展。如果您使用自动配置，则会[在自动配置包中](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#using.auto-configuration.packages)搜索存储库。

以下示例显示了典型的 Spring Data 存储库接口定义：

```
public interface CityRepository extends Repository<City, Long> {
​
    Mono<City> findByNameAndStateAllIgnoringCase(String name, String state);
​
}
```

我们仅仅触及了 Spring Data R2DBC 的皮毛。有关完整的详细信息，请参阅[Spring Data R2DBC 参考文档](https://docs.spring.io/spring-data/r2dbc/docs/3.2.0/reference/html/)。
