SQL 資料庫

Spring Framework 為使用 SQL 資料庫提供了廣泛的支援,從使用 JdbcClientJdbcTemplate 的直接 JDBC 訪問,到像 Hibernate 這樣的完整的“物件關係對映”技術。Spring Data 提供了更高層次的功能:直接從介面建立 Repository 實現,並使用約定從方法名稱生成查詢。

配置 DataSource

Java 的 DataSource 介面提供了一種使用資料庫連線的標準方法。傳統上,DataSource 使用一個 URL 和一些憑據來建立資料庫連線。

有關更高階的示例,通常是為了完全控制 DataSource 的配置,請參閱“操作指南”中的配置自定義 DataSource 部分。

嵌入式資料庫支援

使用記憶體中的嵌入式資料庫開發應用程式通常很方便。顯然,記憶體資料庫不提供持久儲存。您需要在應用程式啟動時填充資料庫,並準備好在應用程式結束時丟棄資料。

“操作指南”部分包含有關如何初始化資料庫的章節

Spring Boot 可以自動配置嵌入式 H2HSQLDerby 資料庫。您無需提供任何連線 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 自動配置。

DataSource 配置

DataSource 配置由 spring.datasource.* 中的外部配置屬性控制。例如,您可以在 application.properties 中宣告以下部分

  • 屬性

  • YAML

spring.datasource.url=jdbc:mysql:///test
spring.datasource.username=dbuser
spring.datasource.password=dbpass
spring:
  datasource:
    url: "jdbc:mysql:///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.*)微調特定於實現的設定。有關更多詳細資訊,請參閱您正在使用的連線池實現的文件。

例如,如果您使用 Tomcat 連線池,您可以自定義許多額外的設定,如下例所示

  • 屬性

  • YAML

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 Boot 使用以下演算法選擇特定的實現

  1. 我們偏愛 HikariCP 的效能和併發性。如果 HikariCP 可用,我們總是選擇它。

  2. 否則,如果 Tomcat 池化 DataSource 可用,我們使用它。

  3. 否則,如果 Commons DBCP2 可用,我們使用它。

  4. 如果 HikariCP、Tomcat 和 DBCP2 均不可用,並且 Oracle UCP 可用,我們使用它。

如果您使用 spring-boot-starter-jdbcspring-boot-starter-data-jpa starter,您會自動獲得對 HikariCP 的依賴。

您可以透過設定 spring.datasource.type 屬性完全繞過該演算法並指定要使用的連線池。如果您在 Tomcat 容器中執行應用程式,這一點尤其重要,因為 tomcat-jdbc 預設提供。

始終可以使用 DataSourceBuilder 手動配置其他連線池。如果您定義自己的 DataSource bean,則不會發生自動配置。DataSourceBuilder 支援以下連線池

連線到 JNDI DataSource

如果您將 Spring Boot 應用程式部署到應用程式伺服器,您可能希望使用應用程式伺服器的內建功能配置和管理 DataSource,並透過 JNDI 訪問它。

spring.datasource.jndi-name 屬性可以用作 spring.datasource.urlspring.datasource.usernamespring.datasource.password 屬性的替代方案,用於從特定的 JNDI 位置訪問 DataSource。例如,application.properties 中的以下部分顯示瞭如何訪問 JBoss AS 定義的 DataSource

  • 屬性

  • YAML

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

使用 JdbcTemplate

Spring 的 JdbcTemplateNamedParameterJdbcTemplate 類是自動配置的,您可以將它們直接自動注入到您自己的 bean 中,如下例所示

  • Java

  • Kotlin

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.* 屬性自定義模板的一些屬性,如下例所示

  • 屬性

  • YAML

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

如果需要調整 SQL 異常,您可以定義自己的 SQLExceptionTranslator bean,以便將其與自動配置的 JdbcTemplate 相關聯。

NamedParameterJdbcTemplate 在幕後重用相同的 JdbcTemplate 例項。如果定義了多個 JdbcTemplate 且不存在主候選者,則不自動配置 NamedParameterJdbcTemplate

使用 JdbcClient

Spring 的 JdbcClient 根據 NamedParameterJdbcTemplate 的存在自動配置。您也可以將其直接注入到您自己的 bean 中,如下例所示

  • Java

  • Kotlin

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.* 屬性進行的任何自定義也會在客戶端中考慮。

JPA 和 Spring Data JPA

Java Persistence API 是一種標準技術,允許您將物件“對映”到關係資料庫。spring-boot-starter-data-jpa POM 提供了一種快速入門的方法。它提供了以下關鍵依賴項

  • Hibernate:最流行的 JPA 實現之一。

  • Spring Data JPA:幫助您實現基於 JPA 的儲存庫。

  • Spring ORM:Spring Framework 提供的核心 ORM 支援。

我們在這裡不會深入介紹 JPA 或 Spring Data 的太多細節。您可以遵循 spring.io 上的 使用 JPA 訪問資料 指南,並閱讀 Spring Data JPAHibernate 參考文件。

實體類

傳統上,JPA “實體”類是在 persistence.xml 檔案中指定的。使用 Spring Boot,此檔案不再必要,而是使用“實體掃描”。預設情況下,自動配置包 會被掃描。

任何使用 @Entity@Embeddable@MappedSuperclass 註解的類都會被考慮。典型的實體類類似於以下示例

  • Java

  • Kotlin

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 Data 的 Query 註解來標註您的方法。

Spring Data 儲存庫通常擴充套件自 RepositoryCrudRepository 介面。如果您使用自動配置,自動配置包 會被搜尋以查詢儲存庫。

您可以使用 @EnableJpaRepositories 自定義查詢儲存庫的位置。

以下示例顯示了一個典型的 Spring Data 儲存庫介面定義

  • Java

  • Kotlin

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 的執行器。

當使用延遲或懶惰引導時,請確保在應用程式上下文引導階段之後延遲對 JPA 基礎設施的任何訪問。您可以使用 SmartInitializingSingleton 來呼叫任何需要 JPA 基礎設施的初始化。對於作為 Spring Bean 建立的 JPA 元件(例如轉換器),請使用 ObjectProvider 來延遲依賴項的解析(如果有的話)。

我們剛剛觸及了 Spring Data JPA 的皮毛。有關完整詳細資訊,請參閱 Spring Data JPA 參考文件

Spring Data Envers 儲存庫

如果 Spring Data Envers 可用,JPA 儲存庫會自動配置以支援典型的 Envers 查詢。

要使用 Spring Data Envers,請確保您的儲存庫擴充套件自 RevisionRepository,如下例所示

  • Java

  • Kotlin

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 資料庫

預設情況下,JPA 資料庫< strong>僅在您使用嵌入式資料庫(H2、HSQL 或 Derby)時自動建立。您可以使用 spring.jpa.* 屬性顯式配置 JPA 設定。例如,要建立和刪除表,您可以在 application.properties 中新增以下行

  • 屬性

  • YAML

spring.jpa.hibernate.ddl-auto=create-drop
spring:
  jpa:
    hibernate.ddl-auto: "create-drop"
Hibernate 自己的內部屬性名稱(如果您碰巧記得更清楚)是 hibernate.hbm2ddl.auto。您可以設定它以及其他 Hibernate 本機屬性,方法是使用 spring.jpa.properties.*(在將它們新增到實體管理器之前會剝離字首)。以下行顯示了為 Hibernate 設定 JPA 屬性的示例
  • 屬性

  • YAML

spring.jpa.properties.hibernate.globally_quoted_identifiers=true
spring:
  jpa:
    properties:
      hibernate:
        "globally_quoted_identifiers": "true"

上例中的行將 hibernate.globally_quoted_identifiers 屬性的值 true 傳遞給 Hibernate 實體管理器。

預設情況下,DDL 執行(或驗證)會延遲到 ApplicationContext 啟動之後。

在檢視中開啟 EntityManager

如果您正在執行 Web 應用程式,Spring Boot 預設註冊 OpenEntityManagerInViewInterceptor 以應用“在檢視中開啟 EntityManager”模式,從而允許在 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 的完整詳細資訊,請參閱參考文件

使用 H2 Web 控制檯

H2 資料庫 提供了一個 基於瀏覽器的控制檯,Spring Boot 可以為您自動配置。當滿足以下條件時,控制檯會自動配置

  • 您正在開發一個基於 Servlet 的 Web 應用程式。

  • com.h2database:h2 在類路徑上。

  • 您正在使用 Spring Boot 的開發工具

如果您沒有使用 Spring Boot 的開發工具但仍然希望使用 H2 控制檯,您可以將 spring.h2.console.enabled 屬性配置為 true
H2 控制檯僅用於開發期間,因此您應注意確保在生產環境中未將 spring.h2.console.enabled 設定為 true

更改 H2 控制檯路徑

預設情況下,控制檯可在 /h2-console 訪問。您可以使用 spring.h2.console.path 屬性自定義控制檯的路徑。

在安全應用程式中訪問 H2 控制檯

H2 控制檯使用框架,並且由於它僅用於開發,因此不實現 CSRF 保護措施。如果您的應用程式使用 Spring Security,則需要將其配置為

  • 停用針對控制檯請求的 CSRF 保護,

  • 在控制檯的響應上設定標頭 X-Frame-OptionsSAMEORIGIN

有關 CSRFX-Frame-Options 標頭的更多資訊可以在 Spring Security 參考指南中找到。

在簡單的設定中,可以使用如下所示的 SecurityFilterChain

  • Java

  • Kotlin

import org.springframework.boot.security.autoconfigure.web.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) {
		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 面向物件查詢 (jOOQ) 是 Data Geekery 的一個流行產品,它從您的資料庫生成 Java 程式碼,並透過其流暢的 API 讓您構建型別安全的 SQL 查詢。商業版和開源版都可以與 Spring Boot 一起使用。

程式碼生成

為了使用 jOOQ 型別安全查詢,您需要從資料庫模式生成 Java 類。您可以按照 jOOQ 使用者手冊 中的說明進行操作。如果您使用 jooq-codegen-maven 外掛,並且還使用 spring-boot-starter-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>

使用 DSLContext

jOOQ 提供的流暢 API 透過 DSLContext 介面啟動。Spring Boot 將 DSLContext 自動配置為 Spring Bean,並將其連線到您的應用程式 DataSource。要使用 DSLContext,您可以注入它,如下例所示

  • Java

  • Kotlin

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 來構建查詢,如下例所示

  • Java

  • Kotlin

	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 無法檢測到方言,它將使用 DEFAULT

Spring Boot 只能自動配置 jOOQ 開源版本支援的方言。

自定義 jOOQ

透過定義自己的 DefaultConfigurationCustomizer bean 可以實現更高階的自定義,該 bean 將在建立 Configuration @Bean 之前呼叫。這優先於自動配置應用的任何內容。

如果您想完全控制 jOOQ 配置,您還可以建立自己的 Configuration @Bean

使用 R2DBC

Reactive Relational Database Connectivity (R2DBC) 專案將響應式程式設計 API 帶入關係資料庫。R2DBC 的 Connection 提供了一種使用非阻塞資料庫連線的標準方法。連線由 ConnectionFactory 提供,類似於 JDBC 的 DataSource

ConnectionFactory 配置由 spring.r2dbc.* 中的外部配置屬性控制。例如,您可以在 application.properties 中宣告以下部分

  • 屬性

  • YAML

spring.r2dbc.url=r2dbc:postgresql:///test
spring.r2dbc.username=dbuser
spring.r2dbc.password=dbpass
spring:
  r2dbc:
    url: "r2dbc:postgresql:///test"
    username: "dbuser"
    password: "dbpass"
您無需指定驅動程式類名,因為 Spring Boot 從 R2DBC 的 Connection Factory 發現中獲取驅動程式。
至少應提供 URL。URL 中指定的資訊優先於單個屬性,即 nameusernamepassword 和池化選項。
“操作指南”部分包含有關如何初始化資料庫的章節

要自定義由 ConnectionFactory 建立的連線,即設定您不想(或不能)在中央資料庫配置中配置的特定引數,您可以使用 ConnectionFactoryOptionsBuilderCustomizer @Bean。以下示例顯示瞭如何手動覆蓋資料庫埠,而其他選項則從應用程式配置中獲取

  • Java

  • Kotlin

import io.r2dbc.spi.ConnectionFactoryOptions;

import org.springframework.boot.r2dbc.autoconfigure.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.r2dbc.autoconfigure.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 連線選項

  • Java

  • Kotlin

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

import io.r2dbc.postgresql.PostgresqlConnectionFactoryProvider;

import org.springframework.boot.r2dbc.autoconfigure.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.r2dbc.autoconfigure.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) 以重新啟用它。

嵌入式資料庫支援

JDBC 支援類似,Spring Boot 可以自動配置嵌入式資料庫以用於響應式使用。您無需提供任何連線 URL。您只需包含對要使用的嵌入式資料庫的構建依賴項,如下例所示

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

如果您在測試中使用此功能,您可能會注意到無論您使用多少個應用程式上下文,整個測試套件都會重複使用相同的資料庫。如果您希望確保每個上下文都有一個單獨的嵌入式資料庫,您應該將 spring.r2dbc.generate-unique-name 設定為 true

使用 DatabaseClient

一個 DatabaseClient bean 是自動配置的,您可以將其直接自動注入到您自己的 bean 中,如下例所示

  • Java

  • Kotlin

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 Data 的 @Query 註解來標註您的方法。

Spring Data 儲存庫通常擴充套件自 RepositoryCrudRepository 介面。如果您使用自動配置,自動配置包 會被搜尋以查詢儲存庫。

以下示例顯示了一個典型的 Spring Data 儲存庫介面定義

  • Java

  • Kotlin

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 參考文件
© . This site is unofficial and not affiliated with VMware.