对于最新稳定版本,请使用 Spring Boot 4.0.4spring-doc.cadn.net.cn

SQL 数据库

Spring 框架为操作 SQL 数据库提供了广泛的支持,从使用 JdbcClientJdbcTemplate 进行直接的 JDBC 访问,到完整的“对象关系映射”技术(如 Hibernate)。 Spring Data 提供了更进一步的功能:直接从接口创建 Repository 实现,并利用约定根据方法名生成查询。spring-doc.cadn.net.cn

配置数据源

Java 的 DataSource 接口提供了一种使用数据库连接的标准方法。 传统上,DataSource 会使用 URL 以及一些凭据来建立数据库连接。spring-doc.cadn.net.cn

参见“How-to Guides”中的配置自定义数据源部分,以获取更高级的示例,通常用于完全控制 DataSource 的配置。

嵌入式数据库支持

使用内嵌内存数据库开发应用程序通常很方便。 显然,内存数据库不提供持久存储功能。 您需要在应用程序启动时填充您的数据库,并准备在应用程序结束时丢弃数据。spring-doc.cadn.net.cn

"如何指南"部分包含了一个有关如何使用基本SQL脚本初始化数据库的xref page

Spring Boot 可以自动配置嵌入式 H2HSQLDerby 数据库。 你无需提供任何连接 URL。 你只需在构建依赖中包含想要使用的嵌入式数据库即可。 如果 classpath 中存在多个嵌入式数据库,请设置 spring.datasource.embedded-database-connection 配置属性来控制使用哪一个。 将该属性设置为 none 可禁用嵌入式数据库的自动配置。spring-doc.cadn.net.cn

如果在测试中使用此功能,可能会注意到整个测试套件都会重用同一个数据库,而与您使用的应用程序上下文数量无关。 如果您希望确保每个上下文都有一个单独的嵌入式数据库,请将spring.datasource.generate-unique-name设置为truespring-doc.cadn.net.cn

例如,典型的POM依赖关系如下:spring-doc.cadn.net.cn

<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-doc.cadn.net.cn

数据源配置

Data Source 配置由外部配置属性 spring.datasource.* 控制。 例如,你可以在 application.properties 中声明以下部分:spring-doc.cadn.net.cn

spring.datasource.url=jdbc:mysql://localhost/test
spring.datasource.username=dbuser
spring.datasource.password=dbpass
spring:
  datasource:
    url: "jdbc:mysql://localhost/test"
    username: "dbuser"
    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 API 文档以了解更多支持的选项。 这些是标准选项,无论 实际实现 如何均可生效。 还可以通过使用各自的前缀(spring.datasource.hikari.*spring.datasource.tomcat.*spring.datasource.dbcp2.*spring.datasource.oracleucp.*)来微调特定于实现的设置。 有关更多详细信息,请参阅您所使用的连接池实现的文档。spring-doc.cadn.net.cn

例如,如果你使用 Tomcat 连接池,你可以自定义许多其他设置,如以下示例所示:spring-doc.cadn.net.cn

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

这将会设置连接池在没有可用连接时等待10000毫秒后抛出异常,最大连接数限制为50,并在从池中借用连接前验证连接。spring-doc.cadn.net.cn

支持的连接池

Spring Boot 使用以下算法来选择特定实现:spring-doc.cadn.net.cn

  1. 我们更倾向于使用HikariCP,因为它具有出色的性能和并发能力。 如果 HikariCP 可用,我们始终会选择它。spring-doc.cadn.net.cn

  2. 否则,如果可用的 Tomcat 连接池 DataSource,我们将使用它。spring-doc.cadn.net.cn

  3. 否则,如果 Commons DBCP2 可用,我们将使用它。spring-doc.cadn.net.cn

  4. 如果没有 HikariCP、Tomcat 和 DBCP2 可用,而 Oracle UCP 可用,则我们使用 Oracle UCP。spring-doc.cadn.net.cn

如果您使用了spring-boot-starter-jdbcspring-boot-starter-data-jpaStarters,将自动依赖于HikariCP。

您完全可以绕过该算法,并通过设置spring.datasource.type属性来指定要使用的连接池。 这在您的应用程序运行在Tomcat容器中时尤为重要,因为默认情况下会提供tomcat-jdbcspring-doc.cadn.net.cn

始终可以使用 DataSourceBuilder 手动配置其他连接池。 如果您定义了自己的 DataSource Bean,则不会发生自动配置。 DataSourceBuilder 支持以下连接池:spring-doc.cadn.net.cn

连接到 JNDI 数据源

如果您将Spring Boot应用程序部署到应用服务器上,您可能希望使用应用服务器的内置功能来配置和管理DataSource,并通过JNDI访问它。spring-doc.cadn.net.cn

spring.datasource.jndi-name 属性可用作 spring.datasource.urlspring.datasource.usernamespring.datasource.password 属性的替代方案,用于从特定 JNDI 位置访问 DataSource。 例如,application.properties 中的以下部分展示了如何访问由 JBoss AS 定义的 DataSourcespring-doc.cadn.net.cn

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

使用 JdbcTemplate

Spring 的 JdbcTemplateNamedParameterJdbcTemplate 类是自动配置的,您可以将它们直接自动装配到您自己的 Bean 中,如下例所示:spring-doc.cadn.net.cn

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

@Component
public class MyBean {

	private final JdbcTemplate jdbcTemplate;

	public MyBean(JdbcTemplate jdbcTemplate) {
		this.jdbcTemplate = jdbcTemplate;
	}

	public void doSomething() {
		this.jdbcTemplate ...
	}

}
import org.springframework.jdbc.core.JdbcTemplate
import org.springframework.stereotype.Component

@Component
class MyBean(private val jdbcTemplate: JdbcTemplate) {

	fun doSomething() {
		jdbcTemplate.execute("delete from customer")
	}

}

您可以使用 spring.jdbc.template.* 属性来自定义模板的一些属性,如下例所示:spring-doc.cadn.net.cn

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

如果需要调整SQL异常,则可以定义自己的SQLExceptionTranslator Bean,使其与自动配置的JdbcTemplate关联。spring-doc.cadn.net.cn

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

使用 JdbcClient

Spring 的 JdbcClient 会根据 NamedParameterJdbcTemplate 的存在进行自动配置。 您也可以像以下示例所示,直接将其注入到您自己的 Bean 中:spring-doc.cadn.net.cn

import org.springframework.jdbc.core.simple.JdbcClient;
import org.springframework.stereotype.Component;

@Component
public class MyBean {

	private final JdbcClient jdbcClient;

	public MyBean(JdbcClient jdbcClient) {
		this.jdbcClient = jdbcClient;
	}

	public void doSomething() {
		this.jdbcClient ...
	}

}
import org.springframework.jdbc.core.simple.JdbcClient
import org.springframework.stereotype.Component

@Component
class MyBean(private val jdbcClient: JdbcClient) {

	fun doSomething() {
		jdbcClient.sql("delete from customer").update()
	}

}

如果您依赖自动配置来创建底层的 JdbcTemplate,那么使用 spring.jdbc.template.* 属性进行的任何自定义也会在客户端中生效。spring-doc.cadn.net.cn

JPA 和 Spring Data JPA

The Java Persistence API 是一种标准技术,可以让您将对象“映射”到关系数据库。 The spring-boot-starter-data-jpa POM 提供了一种快速入门的方式。 它提供了以下关键依赖项:spring-doc.cadn.net.cn

我们不会过多地深入讨论JPA或Spring Data。 您可以跟随从Spring.io 获取数据的JPA指南,并阅读Spring Data JPAHibernate参考文档。

实体类

传统上,JPA “Entity” 类是在一个 persistence.xml 文件中指定的。 在 Spring Boot 中,不再需要这个文件,并且使用了“Entity 扫描”替代。 默认情况下,自动配置包会被扫描。spring-doc.cadn.net.cn

任何标注了 @Entity@Embeddable@MappedSuperclass 的类都将被考虑。 一个典型的实体类类似于以下示例:spring-doc.cadn.net.cn

import java.io.Serializable;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;

@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

}
import jakarta.persistence.Column
import jakarta.persistence.Entity
import jakarta.persistence.GeneratedValue
import jakarta.persistence.Id
import java.io.Serializable

@Entity
class City : Serializable {

	@Id
	@GeneratedValue
	private val id: Long? = null

	@Column(nullable = false)
	var name: String? = null
		private set

	// ... etc
	@Column(nullable = false)
	var state: String? = null
		private set

	// ... additional members, often include @OneToMany mappings

	protected constructor() {
		// no-args constructor required by JPA spec
		// this one is protected since it should not be used directly
	}

	constructor(name: String?, state: String?) {
		this.name = name
		this.state = state
	}

}
您可以通过使用 @EntityScan 注解来自定义实体扫描位置。 请参阅“操作指南”中的 将 @Entity 定义与 Spring 配置分离 部分。

Spring Data JPA 仓库

Spring Data JPA 仓库是您可以定义的接口,用于访问数据。 JPA 查询会根据您的方法名称自动生成。 例如,一个 CityRepository 接口可能会声明一个 findAllByState(String state) 方法,用于查找给定州内的所有城市。spring-doc.cadn.net.cn

对于更复杂的查询,您可以使用 Spring Data 的 Query 注解来标注您的方法。spring-doc.cadn.net.cn

Spring Data 仓库通常扩展自 RepositoryCrudRepository 接口。 如果您使用自动配置,系统将在 自动配置包 中搜索仓库。spring-doc.cadn.net.cn

您可以使用 @EnableJpaRepositories 自定义查找仓库的位置。

以下示例展示了典型的Spring Data仓库接口定义:spring-doc.cadn.net.cn

import org.springframework.boot.docs.data.sql.jpaandspringdata.entityclasses.City;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.Repository;

public interface CityRepository extends Repository<City, Long> {

	Page<City> findAll(Pageable pageable);

	City findByNameAndStateAllIgnoringCase(String name, String state);

}
import org.springframework.boot.docs.data.sql.jpaandspringdata.entityclasses.City
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.data.repository.Repository

interface CityRepository : Repository<City?, Long?> {

	fun findAll(pageable: Pageable?): Page<City?>?

	fun findByNameAndStateAllIgnoringCase(name: String?, state: String?): City?

}

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

使用延迟或惰性引导时,请确保在应用程序上下文引导阶段之后再进行对 JPA 基础设施的任何访问。 您可以使用 SmartInitializingSingleton 来调用任何需要 JPA 基础设施的初始化操作。 对于作为 Spring Bean 创建的 JPA 组件(例如转换器),请使用 ObjectProvider 来延迟依赖项的解析(如果存在)。spring-doc.cadn.net.cn

我们对 Spring Data JPA 的介绍只是浅尝辄止。 有关完整详细信息,请参阅Spring Data JPA 参考文档

Spring Data Envers 仓库

如果 Spring Data Envers 可用,JPA 存储库将自动配置以支持典型的 Envers 查询。spring-doc.cadn.net.cn

要使用 Spring Data Envers,请确保您的仓库继承自 RevisionRepository,如下例所示:spring-doc.cadn.net.cn

import org.springframework.boot.docs.data.sql.jpaandspringdata.entityclasses.Country;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.Repository;
import org.springframework.data.repository.history.RevisionRepository;

public interface CountryRepository extends RevisionRepository<Country, Long, Integer>, Repository<Country, Long> {

	Page<Country> findAll(Pageable pageable);

}
import org.springframework.boot.docs.data.sql.jpaandspringdata.entityclasses.Country
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.data.repository.Repository
import org.springframework.data.repository.history.RevisionRepository

interface CountryRepository :
		RevisionRepository<Country?, Long?, Int>,
		Repository<Country?, Long?> {

	fun findAll(pageable: Pageable?): Page<Country?>?

}
对于更多详细信息,请参阅Spring Data Envers 参考文档

创建和删除 JPA 数据库

By default, JPA 数据库仅在使用嵌入式数据库(H2、HSQL 或 Derby)时才会自动创建。
你可以通过使用 spring.jpa.* 属性显式地配置 JPA 设置。
例如,要创建和删除表,你可以在你的 application.properties 中添加以下行:spring-doc.cadn.net.cn

spring.jpa.hibernate.ddl-auto=create-drop
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
spring:
  jpa:
    properties:
      hibernate:
        "globally_quoted_identifiers": "true"

该示例中的行将true的值作为hibernate.globally_quoted_identifiers属性传递给Hibernate实体管理器。spring-doc.cadn.net.cn

默认情况下,DDL 执行(或验证)会延迟到 ApplicationContext 启动后进行。spring-doc.cadn.net.cn

视图中的开放实体管理器

如果您正在运行一个 Web 应用程序,Spring Boot 默认会注册 OpenEntityManagerInViewInterceptor 以应用“在视图中打开实体管理器”模式,从而允许在 Web 视图中进行延迟加载。 如果您不希望此行为,应在您的 application.properties 中将 spring.jpa.open-in-view 设置为 falsespring-doc.cadn.net.cn

Spring Data JDBC

Spring Data 包含对 JDBC 的仓库支持,并会自动为 CrudRepository 上的方法生成 SQL。 对于更高级的查询,提供了 @Query 注解。spring-doc.cadn.net.cn

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

为了解更多信息,请参阅 参考文档

使用 H2 的 Web 控制台

H2数据库提供了一个基于浏览器的控制台,Spring Boot 可以为你自动配置该控制台。 当满足以下条件时,该控制台将被自动配置:spring-doc.cadn.net.cn

如果您不使用 Spring Boot 的开发工具但仍然希望利用 H2 的控制台,可以将 spring.h2.console.enabled 属性配置为 true
The H2 console is only intended for use during development, so you should take care to ensure that spring.h2.console.enabled is not set to true in production.

更改 H2 控制台的路径

默认情况下,控制台可在 /h2-console 处访问。 您可以使用 spring.h2.console.path 属性来自定义控制台的路径。spring-doc.cadn.net.cn

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

H2 Console 使用了框架,并且由于其仅用于开发目的,因此未实现 CSRF 保护措施。<br/>如果您的应用程序使用了 Spring Security,请对其进行配置以spring-doc.cadn.net.cn

更多关于CSRF和头部信息X-Frame-Options的信息可以在Spring Security 参考手册中找到。spring-doc.cadn.net.cn

在简单的设置中,可以使用如下所示的 SecurityFilterChainspring-doc.cadn.net.cn

import org.springframework.boot.autoconfigure.security.servlet.PathRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.CsrfConfigurer;
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer.FrameOptionsConfig;
import org.springframework.security.web.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(CsrfConfigurer::disable);
		http.headers((headers) -> headers.frameOptions(FrameOptionsConfig::sameOrigin));
		return http.build();
	}


}
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Profile
import org.springframework.core.Ordered
import org.springframework.core.annotation.Order
import org.springframework.security.config.Customizer
import org.springframework.security.config.annotation.web.builders.HttpSecurity
import org.springframework.security.web.SecurityFilterChain

@Profile("dev")
@Configuration(proxyBeanMethods = false)
class DevProfileSecurityConfiguration {

	@Bean
	@Order(Ordered.HIGHEST_PRECEDENCE)
	fun h2ConsoleSecurityFilterChain(http: HttpSecurity): SecurityFilterChain {
		return http.authorizeHttpRequests(yourCustomAuthorization())
			.csrf { csrf -> csrf.disable() }
			.headers { headers -> headers.frameOptions { frameOptions -> frameOptions.sameOrigin() } }
			.build()
	}


}
该 H2 控制台仅旨在开发期间使用。 在生产环境中,禁用 CSRF 保护或允许站点框架可能会造成严重的安全风险。
PathRequest.toH2Console() 返回正确的请求匹配器,即使控制台的路径已被自定义。

使用 jOOQ

jOOQ Object Oriented Querying (jOOQ) 是来自 Data Geekery 的一款流行产品,它可以从您的数据库生成 Java 代码,并通过其流畅的 API 构建类型安全的 SQL 查询。 两者商业版和开源版均可与 Spring Boot 结合使用。spring-doc.cadn.net.cn

代码生成

为了使用 jOOQ 的类型安全查询,您需要从数据库模式生成 Java 类。 您可以按照jOOQ 用户手册中的说明进行操作。 如果您使用 jooq-codegen-maven 插件,并且同时使用了 spring-boot-starter-parent“父 POM”,则可以安全地省略该插件的 <version> 标签。 您还可以使用 Spring Boot 定义的版本变量(例如 h2.version)来声明该插件的数据库依赖项。 以下清单展示了一个示例:spring-doc.cadn.net.cn

<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 提供的流畅 API 是通过 DSLContext 接口启动的。 Spring Boot 会自动配置一个 DSLContext 作为 Spring Bean,并将其连接到您的应用程序 DataSource。 要使用 DSLContext,您可以像以下示例所示那样注入它:spring-doc.cadn.net.cn

import java.util.GregorianCalendar;
import java.util.List;

import org.jooq.DSLContext;

import org.springframework.stereotype.Component;

import static org.springframework.boot.docs.data.sql.jooq.dslcontext.Tables.AUTHOR;

@Component
public class MyBean {

	private final DSLContext create;

	public MyBean(DSLContext dslContext) {
		this.create = dslContext;
	}


}
import org.jooq.DSLContext
import org.springframework.stereotype.Component
import java.util.GregorianCalendar

@Component
class MyBean(private val create: DSLContext) {


}
jOOQ 手册倾向于使用名为 create 的变量来持有 DSLContext

然后,您可以使用 DSLContext 来构建查询,如下例所示:spring-doc.cadn.net.cn

	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);
	fun authorsBornAfter1980(): List<GregorianCalendar> {
		return create.selectFrom<Tables.TAuthorRecord>(Tables.AUTHOR)
			.where(Tables.AUTHOR?.DATE_OF_BIRTH?.greaterThan(GregorianCalendar(1980, 0, 1)))
			.fetch(Tables.AUTHOR?.DATE_OF_BIRTH)
	}

jOOQ SQL 方言

除非配置了spring.jooq.sql-dialect属性,Spring Boot会根据你的数据源来确定要使用的SQL方言。 如果Spring Boot无法检测到方言,则使用DEFAULTspring-doc.cadn.net.cn

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

自定义 jOOQ

更高级的自定义可以通过定义您自己的 DefaultConfigurationCustomizer Bean 来实现,该 Bean 将在创建 Configuration @Bean 之前被调用。 此配置优先于自动配置所应用的任何设置。spring-doc.cadn.net.cn

如果您想完全控制 jOOQ 配置,也可以创建自己的 Configuration @Beanspring-doc.cadn.net.cn

使用 R2DBC

响应式关系数据库连接(R2DBC)项目将响应式编程 API 引入到关系型数据库中。 R2DBC 的 Connection 提供了一种使用非阻塞数据库连接的标准方法。 这些连接是通过使用 ConnectionFactory 来提供的,类似于在 JDBC 中使用 DataSourcespring-doc.cadn.net.cn

ConnectionFactory 配置由 spring.r2dbc.* 中的外部配置属性控制。 例如,您可以在 application.properties 中声明以下部分:spring-doc.cadn.net.cn

spring.r2dbc.url=r2dbc:postgresql://localhost/test
spring.r2dbc.username=dbuser
spring.r2dbc.password=dbpass
spring:
  r2dbc:
    url: "r2dbc:postgresql://localhost/test"
    username: "dbuser"
    password: "dbpass"
您无需指定驱动类名称,因为 Spring Boot 会从 R2DBC 的连接工厂发现中获取驱动。
至少需要提供URL。 URL中的信息优先于个别属性,即nameusernamepassword和连接池选项。
"如何指南"部分包含了一个有关如何使用基本SQL脚本初始化数据库的xref page

要自定义由 ConnectionFactory 创建的连接,即设置您不希望(或无法)在中央数据库配置中配置的特定参数,您可以使用 ConnectionFactoryOptionsBuilderCustomizer @Bean。 以下示例展示了如何在其余选项取自应用程序配置的同时,手动覆盖数据库端口:spring-doc.cadn.net.cn

import io.r2dbc.spi.ConnectionFactoryOptions;

import org.springframework.boot.autoconfigure.r2dbc.ConnectionFactoryOptionsBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
public class MyR2dbcConfiguration {

	@Bean
	public ConnectionFactoryOptionsBuilderCustomizer connectionFactoryPortCustomizer() {
		return (builder) -> builder.option(ConnectionFactoryOptions.PORT, 5432);
	}

}
import io.r2dbc.spi.ConnectionFactoryOptions
import org.springframework.boot.autoconfigure.r2dbc.ConnectionFactoryOptionsBuilderCustomizer
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration(proxyBeanMethods = false)
class MyR2dbcConfiguration {

	@Bean
	fun connectionFactoryPortCustomizer(): ConnectionFactoryOptionsBuilderCustomizer {
		return ConnectionFactoryOptionsBuilderCustomizer { builder ->
			builder.option(ConnectionFactoryOptions.PORT, 5432)
		}
	}

}

以下示例展示了如何设置一些PostgreSQL连接选项:spring-doc.cadn.net.cn

import java.util.HashMap;
import java.util.Map;

import io.r2dbc.postgresql.PostgresqlConnectionFactoryProvider;

import org.springframework.boot.autoconfigure.r2dbc.ConnectionFactoryOptionsBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@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);
	}

}
import io.r2dbc.postgresql.PostgresqlConnectionFactoryProvider
import org.springframework.boot.autoconfigure.r2dbc.ConnectionFactoryOptionsBuilderCustomizer
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration(proxyBeanMethods = false)
class MyPostgresR2dbcConfiguration {

	@Bean
	fun postgresCustomizer(): ConnectionFactoryOptionsBuilderCustomizer {
		val options: MutableMap<String, String> = HashMap()
		options["lock_timeout"] = "30s"
		options["statement_timeout"] = "60s"
		return ConnectionFactoryOptionsBuilderCustomizer { builder ->
			builder.option(PostgresqlConnectionFactoryProvider.OPTIONS, options)
		}
	}

}

当存在 ConnectionFactory Bean 时,常规的 JDBC DataSource 自动配置将失效。 如果您希望保留 JDBC DataSource 自动配置,并且能够接受在响应式应用中使用阻塞式 JDBC API 的风险,可以在应用程序中的 @Configuration 类上添加 @Import(DataSourceAutoConfiguration.class) 以重新启用它。spring-doc.cadn.net.cn

嵌入式数据库支持

Similarly to JDBC 支持,Spring Boot 可以自动配置嵌入式数据库用于响应式使用。
你无需提供任何连接 URL。
你只需要包含一个构建依赖项来使用你想使用的嵌入式数据库,例如如下所示的示例:
spring-doc.cadn.net.cn

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

如果在测试中使用此功能,可能会注意到整个测试套件都会重用同一个数据库,而与您使用的应用程序上下文数量无关。 如果您希望确保每个上下文都有一个单独的嵌入式数据库,请将spring.r2dbc.generate-unique-name设置为truespring-doc.cadn.net.cn

使用 DatabaseClient

一个 DatabaseClient Bean 会被自动配置,您可以像以下示例所示,直接将其自动装配到您自己的 Bean 中:spring-doc.cadn.net.cn

import java.util.Map;

import reactor.core.publisher.Flux;

import org.springframework.r2dbc.core.DatabaseClient;
import org.springframework.stereotype.Component;

@Component
public class MyBean {

	private final DatabaseClient databaseClient;

	public MyBean(DatabaseClient databaseClient) {
		this.databaseClient = databaseClient;
	}

	// ...

	public Flux<Map<String, Object>> someMethod() {
		return this.databaseClient.sql("select * from user").fetch().all();
	}

}
import org.springframework.r2dbc.core.DatabaseClient
import org.springframework.stereotype.Component
import reactor.core.publisher.Flux

@Component
class MyBean(private val databaseClient: DatabaseClient) {

	// ...

	fun someMethod(): Flux<Map<String, Any>> {
		return databaseClient.sql("select * from user").fetch().all()
	}

}

Spring Data R2DBC 仓库

Spring Data R2DBC 仓库是您可以定义的接口,用于访问数据。 查询会根据您的方法名称自动生成。 例如,一个 CityRepository 接口可能会声明一个 findAllByState(String state) 方法,用于查找给定州内的所有城市。spring-doc.cadn.net.cn

对于更复杂的查询,您可以使用 Spring Data 的 @Query 注解来标注您的方法。spring-doc.cadn.net.cn

Spring Data 仓库通常扩展自 RepositoryCrudRepository 接口。 如果您使用自动配置,系统将在 自动配置包 中搜索仓库。spring-doc.cadn.net.cn

以下示例展示了典型的Spring Data仓库接口定义:spring-doc.cadn.net.cn

import reactor.core.publisher.Mono;

import org.springframework.data.repository.Repository;

public interface CityRepository extends Repository<City, Long> {

	Mono<City> findByNameAndStateAllIgnoringCase(String name, String state);

}
import org.springframework.data.repository.Repository
import reactor.core.publisher.Mono

interface CityRepository : Repository<City?, Long?> {

	fun findByNameAndStateAllIgnoringCase(name: String?, state: String?): Mono<City?>?

}
我们对 Spring Data R2DBC 的介绍只是浅尝辄止。如需完整详情,请参阅Spring Data R2DBC 参考文档