SQL Databases

{url-spring-framework-site}[Spring Framework] 提供了广泛的支持以支持使用 SQL 数据库,从直接使用 JDBC 访问 JdbcClientJdbcTemplate,到完整的 “object relational mapping” 技术,如 Hibernate,{url-spring-data-site}[Spring Data] 提供了其他层级功能:直接从界面创建 Repository 实现,并使用约定从方法名称生成查询。

Configure a DataSource

Java 的 javax.sql.DataSource 界面提供了一种与数据库连接一起工作的标准方法,传统上,DataSource 使用 URL 以及一些凭证来建立数据库连接。

有关更高级的示例,请参阅 the “How-to” section,通常用于完全控制 DataSource 的配置。

Embedded Database Support

通过使用内存中嵌入式数据库通常很方便。显然,内存中数据库不提供持久存储,你的应用程序启动时需要填充你的数据库,并且当你的应用程序结束时要准备好丢弃数据。

“How-to” 部分包含 section on how to initialize a database

Spring Boot 可以自动配置嵌入式 H2HSQLDerby 数据库,你不需要提供任何连接 URL,你只需要包含要使用的嵌入式数据库的构建依赖项,如果 classpath 上存在多个嵌入式数据库,设置 configprop: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 能够控制关闭数据库的时间,从而确保在不再需要访问数据库时关闭数据库。

Connection to a Production Database

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

DataSource Configuration

DataSource 配置由 spring.datasource.* 中的外部配置属性控制。例如,您可以在 application.properties 中声明以下部分:

spring:
  datasource:
    url: "jdbc:mysql://localhost/test"
    username: "dbuser"
    password: "dbpass"

您应该至少通过设置 configprop:spring.datasource.url[] 属性指定 URL。否则,Spring Boot 将尝试自动配置一个嵌入式数据库。

Spring Boot 可以从 URL 推导出大多数数据库的 JDBC 驱动程序类。如果您需要指定特定的类,则可以使用 configprop:spring.datasource.driver-class-name[] 属性。

为了创建池化 DataSource ,我们必须能够验证有效的 Driver 类可用,因此我们在执行任何操作之前检查该类。换句话说,如果您设置了 spring.datasource.driver-class-name=com.mysql.jdbc.Driver ,则该类必须可加载。

请参阅 {code-spring-boot-autoconfigure-src}/jdbc/DataSourceProperties.java[DataSourceProperties] 以获取更多受支持的选项。这些是与 the actual implementation 无关的标准选项。还可以通过使用它们各自的前缀 (spring.datasource.hikari., spring.datasource.tomcat.spring.datasource.dbcp2., and spring.datasource.oracleucp.) 来微调特定于实现的设置。请参阅正在使用的连接池实现的文档以获取更多详细信息。

例如,如果您使用 {url-tomcat-docs}/jdbc-pool.html#Common_Attributes[Tomcat 连接池],则可以自定义许多其他设置,如下例所示:

spring:
  datasource:
    tomcat:
      max-wait: 10000
      max-active: 50
      test-on-borrow: true

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

Supported Connection Pools

Spring Boot 使用以下算法选择特定实现:

  1. 我们更喜欢 HikariCP ,因为它具有高性能和并发性。如果 HikariCP 可用,我们总会选择它。

  2. 否则,如果 Tomcat 池化 DataSource 可用,我们就会使用它。

  3. 否则,如果 Commons DBCP2 可用,我们就使用它。

  4. 如果 HikariCP、Tomcat 和 DBCP2 均不可用,并且 Oracle UCP 可用,我们就会使用它。

如果您使用的是 spring-boot-starter-jdbcspring-boot-starter-data-jpa “starters” ,则会自动获得对 HikariCP 的依赖关系。

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

使用 DataSourceBuilder 总是可以手动配置其他连接池。如果你定义了自有 DataSource bean,不会自动配置。DataSourceBuilder 支持以下连接池:

  • HikariCP

  • Tomcat pooling Datasource

  • Commons DBCP2

  • Oracle UCP & OracleDataSource

  • Spring Framework’s SimpleDriverDataSource

  • H2 JdbcDataSource

  • PostgreSQL PGSimpleDataSource

  • C3P0

Connection to a JNDI DataSource

如果你将 Spring Boot 应用程序部署到应用程序服务器,你可以使用应用程序服务器的内置特性配置和管理 DataSource,并通过 JNDI 访问它。

configprop:spring.datasource.jndi-name[] 属性可以用作 configprop:spring.datasource.url[], configprop:spring.datasource.username[], 和 configprop:spring.datasource.password[] 属性的替代方法,以从特定 JNDI 位置访问 DataSource。例如,application.properties 中的以下节显示了如何访问 JBoss AS 定义的 DataSource

spring:
  datasource:
    jndi-name: "java:jboss/datasources/customers"

Using JdbcTemplate

Spring 的 JdbcTemplateNamedParameterJdbcTemplate 类是自动配置的,你可以 @Autowire 直接将其添加到自己的 bean,如以下示例所示:

你可以通过使用 spring.jdbc.template.* 属性来定制模板的一些属性,如以下示例所示:

spring:
  jdbc:
    template:
      max-rows: 500

NamedParameterJdbcTemplate 在幕后重复使用相同的 JdbcTemplate 实例。如果定义了多于一个 JdbcTemplate,但不存在主要候选者,则不会自动配置 NamedParameterJdbcTemplate

Using JdbcClient

Spring 的 JdbcClient 是基于 NamedParameterJdbcTemplate 的存在自动配置的。你也可以直接将其注入到自己的 bean 中,如以下示例所示:

如果你依赖自动配置来创建基础 JdbcTemplate,使用 spring.jdbc.template.* 属性的任何定制也能在客户端中得到考虑。

JPA and Spring Data JPA

Java Persistence API 是一项标准的技术,可以让你将 “map” 对象存储到关系数据库中。spring-boot-starter-data-jpa POM 提供快速入门的方法。它提供以下关键依赖项:

  • Hibernate:最受欢迎的 JPA 实现之一。

  • Spring Data JPA:帮助你实现基于 JPA 的存储库。

  • Spring ORM:Spring Framework 的核心 ORM 支持。

我们在此不会深入讨论 JPA 或 {url-spring-data-site}[Spring Data]。你可以访问 [role="bare"][role="bare"]https://spring.io“Accessing Data with JPA” 指南,并阅读 {url-spring-data-jpa-site}[Spring Data JPA] 和 Hibernate 参考文档。

Entity Classes

传统上,JPA “Entity” 类在 persistence.xml 文件中指定。使用 Spring Boot,无需此文件,而是改用 “Entity Scanning”。默认情况下,会扫描 auto-configuration packages

考虑标注为 @Entity@Embeddable@MappedSuperclass 的任何类。一个典型实体类类似于以下示例:

你可以通过使用 @EntityScan 注释来自定义实体扫描位置。请参阅 “Separate @Entity Definitions from Spring Configuration” 操作指南。

Spring Data JPA Repositories

{url-spring-data-jpa-site}[Spring Data JPA] 存储库是你用来访问数据的可以定义的界面。JPA 查询创建于你的方法名。例如,CityRepository 界面可声明一个 findAllByState(String state) 方法来查找给定状态的所有城市。

对于更复杂查询,你可以在你的方法中添加注释,添加 Spring Data 的 {url-spring-data-jpa-javadoc}/org/springframework/data/jpa/repository/Query.html[Query] 注释。

Spring Data 存储库通常扩展自 {url-spring-data-commons-javadoc}/org/springframework/data/repository/Repository.html[Repository] 或 {url-spring-data-commons-javadoc}/org/springframework/data/repository/CrudRepository.html[CrudRepository] 接口。如果使用自动配置,那么将会检索 auto-configuration packages 存储库。

可以使用 @EnableJpaRepositories 自定义用于查找存储库的位置。

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

Spring Data JPA 存储库支持三种不同的引导模式:默认、延迟和惰性。要启用延迟或惰性引导,将 configprop:spring.data.jpa.repositories.bootstrap-mode[] 属性分别设置为 deferredlazy。在使用延迟或惰性引导时,自动配置的 EntityManagerFactoryBuilder 将使用上下文的 AsyncTaskExecutor,如果存在的话,作为引导执行程序。如果存在多个,那么将会使用名为 applicationTaskExecutor 的那个。

在使用延迟或惰性引导时,确保在应用程序上下文引导阶段后延迟对 JPA 基础设施的任何访问。您可以使用 SmartInitializingSingleton 调用任何需要 JPA 基础设施的初始化。对于作为 Spring bean 创建的 JPA 组件(例如转换器),请在需要时使用 ObjectProvider 延迟解析依赖项。

我们几乎没有涉猎 Spring Data JPA。如果要获得详细信息,请参阅 {url-spring-data-jpa-docs}[Spring Data JPA 参考文档]。

Spring Data Envers Repositories

如果 {url-spring-data-envers-site}[Spring Data Envers] 可用,那么 JPA 存储库将被自动配置为支持典型的 Envers 查询。

要使用 Spring Data Envers,请确保您的存储库扩展自 RevisionRepository,如以下示例中所示:

如果要获得更多详细信息,请查看 {url-spring-data-jpa-docs}/envers.html[Spring Data Envers 参考文档]。

Creating and Dropping JPA Databases

默认情况下,如果您使用嵌入式数据库(H2、HSQL 或 Derby),JPA 数据库将被自动创建 only。您可以使用 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"

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

默认情况下,DDL 执行(或验证)将延迟到 ApplicationContext 开始。还有一个 spring.jpa.generate-ddl 标记,但是如果 Hibernate 自动配置处于活动状态,将不使用它,因为 ddl-auto 设置更加详细。

Open EntityManager in View

如果您运行的是 Web 应用程序,那么 Spring Boot 默认注册 {url-spring-framework-javadoc}/org/springframework/orm/jpa/support/OpenEntityManagerInViewInterceptor.html[OpenEntityManagerInViewInterceptor] 来应用 “Open EntityManager in View” 模式,以允许 Web 视图中的惰性加载。如果您不想要此行为,那么应该在您的 application.properties 中将 spring.jpa.open-in-view 设置为 false

Spring Data JDBC

Spring Data 包括对 JDBC 的存储库支持,并且将为 CrudRepository 上的方法自动生成 SQL。对于更高级的查询,提供了 @Query 注释。

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

如果要获得 Spring Data JDBC 的详细信息,请参阅 {url-spring-data-jdbc-docs}[参考文档]。

Using H2’s Web Console

H2 database 提供了 browser-based console,Spring Boot 可以自动配置它。在满足以下条件时,控制台自动配置:

如果您不使用 Spring Boot 的开发者工具,但仍然希望使用 H2 的控制台,您可以使用 true 配置 configprop:spring.h2.console.enabled[] 属性。

H2 控制台仅用于开发过程中,因此您应该注意确保 spring.h2.console.enabled 在生产中未设置为 true

Changing the H2 Console’s Path

默认情况下,控制台可在 /h2-console 中使用。您可以通过使用 configprop:spring.h2.console.path[] 属性来自定义控制台的路径。

Accessing the H2 Console in a Secured Application

H2 控制台使用框架并且仅供开发使用,因此未实现 CSRF 保护措施。如果您的应用程序使用 Spring Security,则需要将其配置为

  • 停用对控制台请求的 CSRF 保护,

  • 将标头 X-Frame-Options 设置为 SAMEORIGIN 在控制台的响应中。

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

在简单设置中,可以使用如下 SecurityFilterChain

H2 控制台仅用于开发过程中。在生产中,禁用 CSRF 保护或允许网站使用框架可能会产生严重的安全性风险。

PathRequest.toH2Console() 也会在控制台的路径已自定义时返回正确的请求匹配器。

Using jOOQ

面向对象的 jOOQ 查询 ( jOOQ) 是 Data Geekery 的一个流行产品,它根据您的数据库生成 Java 代码,并允许您通过它流畅的 API 构建类型安全的 SQL 查询。商业版和开源版都可与 Spring Boot 配合使用。

Code Generation

要使用 jOOQ 类型安全查询,您需要从数据库架构生成 Java 类。您可以按照 {url-jooq-docs}/#jooq-in-7-steps-step3[jOOQ 用户手册] 中的说明进行操作。如果您使用 jooq-codegen-maven 插件,并且还使用 spring-boot-starter-parent “parent POM”,则可以安全地省略插件的 <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>

Using DSLContext

jOOQ 提供的流畅 API 通过 org.jooq.DSLContext 启动界面。Spring Boot 将 DSLContext 自动配置为 Spring Bean,并将其连接到您的应用程序 DataSource。要使用 DSLContext,您可以注入它,如下例所示:

jOOQ 手册倾向于使用一个名为 create 的变量来保存 DSLContext

然后,你可以使用 DSLContext 来构造你的查询,如下例所示:

jOOQ SQL Dialect

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

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

Customizing jOOQ

可以通过定义你的自定义 DefaultConfigurationCustomizer Bean 来实现更高级的定制,该 Bean 将在创建 org.jooq.Configuration @Bean 之前调用。这优先于自动配置中应用的任何内容。

如果要完全控制 jOOQ 配置,还可以创建你自己的 org.jooq.Configuration @Bean

Using R2DBC

响应式关系型数据库连接 ( R2DBC) 项目将响应式编程 API 引入到了关系型数据库中。R2DBC 的 io.r2dbc.spi.Connection 提供了一种使用非阻塞数据库连接的标准方法。使用 ConnectionFactory 提供连接,类似于使用 JDBC 中的 DataSource

ConnectionFactory 配置通过 spring.r2dbc.* 中的外部配置属性进行控制。例如,你可以在 application.properties 中声明以下部分:

spring:
  r2dbc:
    url: "r2dbc:postgresql://localhost/test"
    username: "dbuser"
    password: "dbpass"

你不必指定驱动程序类名,因为 Spring Boot 会从 R2DBC 的连接工厂发现中获取驱动程序。

至少应该提供 URL。URL 中指定的信息优先于单个属性,即 nameusernamepassword 和连接池选项。

“How-to” 部分包括一个 section on how to initialize a database

要自定义一个 ConnectionFactory 创建的连接,即设置在你的中心数据库配置中你不想 (或不能) 配置的特定参数,可以使用一个 ConnectionFactoryOptionsBuilderCustomizer @Bean。以下示例显示了如何在从应用程序配置中获取其余选项时手动覆盖数据库端口:

以下示例显示了如何设置某些 PostgreSQL 连接选项:

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

Embedded Database Support

the JDBC support 类似,Spring Boot 可以自动配置嵌入式数据库以供响应式使用。你不需要提供任何连接 URL。你只需要将构建依赖项包含到你想要使用的嵌入式数据库,如下例所示:

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

如果你在测试中使用这个功能,你可能会发现无论你使用多少个应用程序上下文,你的整个测试套件都会重复使用同一个数据库。如果你想确保每个上下文都有一个独立的嵌入式数据库,则应该将 spring.r2dbc.generate-unique-name 设置为 true

Using DatabaseClient

`DatabaseClient`bean 自动配置,你可以将它 `@Autowire`直接导入到自己的 bean 中,如下例所示:

Spring Data R2DBC Repositories

Spring Data R2DBC存储库是你用来访问数据的接口。查询会自动从你的方法名创建。例如,一个 `CityRepository`接口可能声明一个 `findAllByState(String state)`方法,用于查找给定状态中的所有城市。

对于更复杂的查询,你可以使用 Spring Data 的 {url-spring-data-r2dbc-javadoc}/org/springframework/data/r2dbc/repository/Query.html[Query] 注释来注释你的方法。

Spring Data 存储库通常扩展自 {url-spring-data-commons-javadoc}/org/springframework/data/repository/Repository.html[Repository] 或 {url-spring-data-commons-javadoc}/org/springframework/data/repository/CrudRepository.html[CrudRepository] 接口。如果使用自动配置,那么将会检索 auto-configuration packages 存储库。

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

我们还只是粗略地介绍了 Spring Data R2DBC。有关完整信息,请参阅 {url-spring-data-r2dbc-docs}[Spring Data R2DBC 参考文档]。