此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Boot 3.4.3! |
SQL 数据库
Spring Framework 为使用 SQL 数据库提供了广泛的支持,通过使用JdbcClient
或JdbcTemplate
完成 Hibernate 等 “对象关系映射” 技术。Spring Data 提供了另一个级别的功能:创建Repository
直接从接口实现,并使用约定从您的方法名称生成查询。
配置 DataSource
Java 的DataSource
interface 提供了一种使用数据库连接的标准方法。
传统上,一个DataSource
使用URL
以及用于建立数据库连接的一些凭证。
有关更高级的示例,请参阅“作指南”的配置自定义 DataSource 部分,通常可以完全控制 DataSource 的配置。 |
嵌入式数据库支持
使用内存中嵌入式数据库开发应用程序通常很方便。 显然,内存数据库不提供持久存储。 您需要在应用程序启动时填充数据库,并准备好在应用程序结束时丢弃数据。
“How-to Guides” 部分包括有关如何初始化数据库的部分。 |
Spring Boot 可以自动配置嵌入式 H2、HSQL 和 Derby 数据库。
您无需提供任何连接 URL。
您只需包含对要使用的嵌入式数据库的构建依赖项。
如果 Classpath 上有多个嵌入式数据库,请将spring.datasource.embedded-database-connection
configuration 属性来控制使用哪一个。
将属性设置为none
禁用嵌入式数据库的自动配置。
如果您在测试中使用此功能,您可能会注意到,无论您使用多少个应用程序上下文,整个测试套件都会重用同一个数据库。
如果要确保每个上下文都有一个单独的嵌入式数据库,则应将 |
例如,典型的 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
:
-
Properties
-
YAML
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 财产。
否则, Spring Boot 会尝试自动配置嵌入式数据库。 |
Spring Boot 可以从 URL 中推断出大多数数据库的 JDBC 驱动程序类。
如果需要指定特定类,可以使用spring.datasource.driver-class-name 财产。 |
对于池化DataSource 要创建,我们需要能够验证有效的Driver class 可用,因此我们在执行任何作之前都会检查一下。
换句话说,如果您将spring.datasource.driver-class-name=com.mysql.jdbc.Driver ,则该类必须是可加载的。 |
看DataSourceProperties
API 文档,了解更多支持的选项。
这些是无论实际实现如何都有效的标准选项。
还可以使用各自的前缀 (spring.datasource.hikari.*
,spring.datasource.tomcat.*
,spring.datasource.dbcp2.*
和spring.datasource.oracleucp.*
).
有关更多详细信息,请参阅您正在使用的连接池实现的文档。
例如,如果您使用 Tomcat 连接池,则可以自定义许多其他设置,如以下示例所示:
-
Properties
-
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 使用以下算法来选择特定实现:
-
我们更喜欢 HikariCP 的性能和并发性。 如果 HikariCP 可用,我们总是会选择它。
-
否则,如果 Tomcat 池化
DataSource
可用,我们使用它。 -
否则,如果 Commons DBCP2 可用,我们就会使用它。
-
如果 HikariCP、Tomcat 和 DBCP2 都不可用,并且 Oracle UCP 可用,则使用它。
如果您使用spring-boot-starter-jdbc 或spring-boot-starter-data-jpa 首先,你会自动获得对 HikariCP 的依赖。 |
您可以完全绕过该算法,并通过设置spring.datasource.type
财产。
如果您在 Tomcat 容器中运行应用程序,这一点尤其重要,因为tomcat-jdbc
默认提供。
其他连接池始终可以手动配置,使用DataSourceBuilder
.
如果您定义自己的DataSource
bean,则不会进行自动配置。
以下连接池由DataSourceBuilder
:
-
光CP
-
Tomcat 池
DataSource
-
共享 DBCP2
-
Oracle UCP 和
OracleDataSource
-
Spring 框架的
SimpleDriverDataSource
-
H2 系列
JdbcDataSource
-
PostgreSQL 数据库
PGSimpleDataSource
-
C3P0
-
振动器
连接到 JNDI DataSource
如果将 Spring Boot 应用程序部署到 Application Server,则可能需要使用 Application Server 的内置功能来配置和管理 DataSource,并使用 JNDI 访问它。
这spring.datasource.jndi-name
属性可以用作spring.datasource.url
,spring.datasource.username
和spring.datasource.password
属性以访问DataSource
从特定的 JNDI 位置。
例如,以下部分application.properties
演示如何访问定义的 JBoss ASDataSource
:
-
Properties
-
YAML
spring.datasource.jndi-name=java:jboss/datasources/customers
spring:
datasource:
jndi-name: "java:jboss/datasources/customers"
使用 JdbcTemplate
Spring的JdbcTemplate
和NamedParameterJdbcTemplate
类是自动配置的,你可以将它们直接自动连接到你自己的 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")
}
}
You can customize some properties of the template by using the spring.jdbc.template.*
properties, as shown in the following example:
-
Properties
-
YAML
spring.jdbc.template.max-rows=500
spring:
jdbc:
template:
max-rows: 500
If tuning of SQL exceptions is required, you can define your own SQLExceptionTranslator
bean so that it is associated with the auto-configured JdbcTemplate
.
The NamedParameterJdbcTemplate
reuses the same JdbcTemplate
instance behind the scenes.
If more than one JdbcTemplate
is defined and no primary candidate exists, the NamedParameterJdbcTemplate
is not auto-configured.
Using JdbcClient
Spring’s JdbcClient
is auto-configured based on the presence of a NamedParameterJdbcTemplate
.
You can inject it directly in your own beans as well, as shown in the following example:
-
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()
}
}
If you rely on auto-configuration to create the underlying JdbcTemplate
, any customization using spring.jdbc.template.*
properties is taken into account in the client as well.
JPA and Spring Data JPA
The Java Persistence API is a standard technology that lets you “map” objects to relational databases.
The spring-boot-starter-data-jpa
POM provides a quick way to get started.
It provides the following key dependencies:
-
Hibernate: One of the most popular JPA implementations.
-
Spring Data JPA: Helps you to implement JPA-based repositories.
-
Spring ORM: Core ORM support from the Spring Framework.
We do not go into too many details of JPA or Spring Data here.
You can follow the Accessing Data with JPA guide from spring.io and read the Spring Data JPA and Hibernate reference documentation.
Entity Classes
Traditionally, JPA “Entity” classes are specified in a persistence.xml
file.
With Spring Boot, this file is not necessary and “Entity Scanning” is used instead.
By default the auto-configuration packages are scanned.
Any classes annotated with @Entity
, @Embeddable
, or @MappedSuperclass
are considered.
A typical entity class resembles the following example:
-
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
}
}
You can customize entity scanning locations by using the @EntityScan
annotation.
See the Separate @Entity Definitions from Spring Configuration section of the “How-to Guides”.
Spring Data JPA Repositories
Spring Data JPA repositories are interfaces that you can define to access data.
JPA queries are created automatically from your method names.
For example, a CityRepository
interface might declare a findAllByState(String state)
method to find all the cities in a given state.
For more complex queries, you can annotate your method with Spring Data’s Query
annotation.
Spring Data repositories usually extend from the Repository
or CrudRepository
interfaces.
If you use auto-configuration, the auto-configuration packages are searched for repositories.
You can customize the locations to look for repositories using @EnableJpaRepositories
.
The following example shows a typical Spring Data repository interface definition:
-
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 repositories support three different modes of bootstrapping: default, deferred, and lazy.
To enable deferred or lazy bootstrapping, set the spring.data.jpa.repositories.bootstrap-mode
property to deferred
or lazy
respectively.
When using deferred or lazy bootstrapping, the auto-configured EntityManagerFactoryBuilder
will use the context’s AsyncTaskExecutor
, if any, as the bootstrap executor.
If more than one exists, the one named applicationTaskExecutor
will be used.
When using deferred or lazy bootstrapping, make sure to defer any access to the JPA infrastructure after the application context bootstrap phase.
You can use SmartInitializingSingleton
to invoke any initialization that requires the JPA infrastructure.
For JPA components (such as converters) that are created as Spring beans, use ObjectProvider
to delay the resolution of dependencies, if any.
We have barely scratched the surface of Spring Data JPA.
For complete details, see the Spring Data JPA reference documentation.
Spring Data Envers Repositories
If Spring Data Envers is available, JPA repositories are auto-configured to support typical Envers queries.
To use Spring Data Envers, make sure your repository extends from RevisionRepository
as shown in the following example:
-
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?>?
}
For more details, check the Spring Data Envers reference documentation.
Creating and Dropping JPA Databases
By default, JPA databases are automatically created only if you use an embedded database (H2, HSQL, or Derby).
You can explicitly configure JPA settings by using spring.jpa.*
properties.
For example, to create and drop tables you can add the following line to your application.properties
:
-
Properties
-
YAML
spring.jpa.hibernate.ddl-auto=create-drop
spring:
jpa:
hibernate.ddl-auto: "create-drop"
Hibernate’s own internal property name for this (if you happen to remember it better) is hibernate.hbm2ddl.auto
.
You can set it, along with other Hibernate native properties, by using spring.jpa.properties.*
(the prefix is stripped before adding them to the entity manager).
The following line shows an example of setting JPA properties for Hibernate:
-
Properties
-
YAML
spring.jpa.properties.hibernate.globally_quoted_identifiers=true
spring:
jpa:
properties:
hibernate:
"globally_quoted_identifiers": "true"
The line in the preceding example passes a value of true
for the hibernate.globally_quoted_identifiers
property to the Hibernate entity manager.
By default, the DDL execution (or validation) is deferred until the ApplicationContext
has started.
Open EntityManager in View
If you are running a web application, Spring Boot by default registers OpenEntityManagerInViewInterceptor
to apply the “Open EntityManager in View” pattern, to allow for lazy loading in web views.
If you do not want this behavior, you should set spring.jpa.open-in-view
to false
in your application.properties
.
Spring Data JDBC
Spring Data includes repository support for JDBC and will automatically generate SQL for the methods on CrudRepository
.
For more advanced queries, a @Query
annotation is provided.
Spring Boot will auto-configure Spring Data’s JDBC repositories when the necessary dependencies are on the classpath.
They can be added to your project with a single dependency on spring-boot-starter-data-jdbc
.
If necessary, you can take control of Spring Data JDBC’s configuration by adding the @EnableJdbcRepositories
annotation or an AbstractJdbcConfiguration
subclass to your application.
For complete details of Spring Data JDBC, see the reference documentation.
Using H2’s Web Console
The H2 database provides a browser-based console that Spring Boot can auto-configure for you.
The console is auto-configured when the following conditions are met:
-
You are developing a servlet-based web application.
-
com.h2database:h2
is on the classpath.
-
You are using Spring Boot’s developer tools.
If you are not using Spring Boot’s developer tools but would still like to make use of H2’s console, you can configure the spring.h2.console.enabled
property with a value of 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.
Changing the H2 Console’s Path
By default, the console is available at /h2-console
.
You can customize the console’s path by using the spring.h2.console.path
property.
Accessing the H2 Console in a Secured Application
H2 Console uses frames and, as it is intended for development only, does not implement CSRF protection measures.
If your application uses Spring Security, you need to configure it to
-
disable CSRF protection for requests against the console,
-
set the header X-Frame-Options
to SAMEORIGIN
on responses from the console.
More information on CSRF and the header X-Frame-Options can be found in the Spring Security Reference Guide.
In simple setups, a SecurityFilterChain
like the following can be used:
-
Java
-
Kotlin
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()
}
}
The H2 console is only intended for use during development.
In production, disabling CSRF protection or allowing frames for a website may create severe security risks.
PathRequest.toH2Console()
returns the correct request matcher also when the console’s path has been customized.
Using jOOQ
jOOQ Object Oriented Querying (jOOQ) is a popular product from Data Geekery which generates Java code from your database and lets you build type-safe SQL queries through its fluent API.
Both the commercial and open source editions can be used with Spring Boot.
Code Generation
In order to use jOOQ type-safe queries, you need to generate Java classes from your database schema.
You can follow the instructions in the jOOQ user manual.
If you use the jooq-codegen-maven
plugin and you also use the spring-boot-starter-parent
“parent POM”, you can safely omit the plugin’s <version>
tag.
You can also use Spring Boot-defined version variables (such as h2.version
) to declare the plugin’s database dependency.
The following listing shows an example:
<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
The fluent API offered by jOOQ is initiated through the DSLContext
interface.
Spring Boot auto-configures a DSLContext
as a Spring Bean and connects it to your application DataSource
.
To use the DSLContext
, you can inject it, as shown in the following example:
-
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) {
}
The jOOQ manual tends to use a variable named create
to hold the DSLContext
.
You can then use the DSLContext
to construct your queries, as shown in the following example:
-
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 Dialect
Unless the spring.jooq.sql-dialect
property has been configured, Spring Boot determines the SQL dialect to use for your datasource.
If Spring Boot could not detect the dialect, it uses DEFAULT
.
Spring Boot can only auto-configure dialects supported by the open source version of jOOQ.
Customizing jOOQ
More advanced customizations can be achieved by defining your own DefaultConfigurationCustomizer
bean that will be invoked prior to creating the Configuration
@Bean
.
This takes precedence to anything that is applied by the auto-configuration.
You can also create your own Configuration
@Bean
if you want to take complete control of the jOOQ configuration.
Using R2DBC
The Reactive Relational Database Connectivity (R2DBC) project brings reactive programming APIs to relational databases.
R2DBC’s Connection
provides a standard method of working with non-blocking database connections.
Connections are provided by using a ConnectionFactory
, similar to a DataSource
with jdbc.
ConnectionFactory
configuration is controlled by external configuration properties in spring.r2dbc.*
.
For example, you might declare the following section in application.properties
:
-
Properties
-
YAML
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"
You do not need to specify a driver class name, since Spring Boot obtains the driver from R2DBC’s Connection Factory discovery.
At least the url should be provided.
Information specified in the URL takes precedence over individual properties, that is name
, username
, password
and pooling options.
The “How-to Guides” section includes a section on how to initialize a database.
To customize the connections created by a ConnectionFactory
, that is, set specific parameters that you do not want (or cannot) configure in your central database configuration, you can use a ConnectionFactoryOptionsBuilderCustomizer
@Bean
.
The following example shows how to manually override the database port while the rest of the options are taken from the application configuration:
-
Java
-
Kotlin
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)
}
}
}
The following examples show how to set some PostgreSQL connection options:
-
Java
-
Kotlin
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)
}
}
}
When a ConnectionFactory
bean is available, the regular JDBC DataSource
auto-configuration backs off.
If you want to retain the JDBC DataSource
auto-configuration, and are comfortable with the risk of using the blocking JDBC API in a reactive application, add @Import(DataSourceAutoConfiguration.class)
on a @Configuration
class in your application to re-enable it.
Embedded Database Support
Similarly to the JDBC support, Spring Boot can automatically configure an embedded database for reactive usage.
You need not provide any connection URLs.
You need only include a build dependency to the embedded database that you want to use, as shown in the following example:
<dependency>
<groupId>io.r2dbc</groupId>
<artifactId>r2dbc-h2</artifactId>
<scope>runtime</scope>
</dependency>
If you are using this feature in your tests, you may notice that the same database is reused by your whole test suite regardless of the number of application contexts that you use.
If you want to make sure that each context has a separate embedded database, you should set spring.r2dbc.generate-unique-name
to true
.
Using DatabaseClient
A DatabaseClient
bean is auto-configured, and you can autowire it directly into your own beans, as shown in the following example:
-
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 Repositories
Spring Data R2DBC repositories are interfaces that you can define to access data.
Queries are created automatically from your method names.
For example, a CityRepository
interface might declare a findAllByState(String state)
method to find all the cities in a given state.
For more complex queries, you can annotate your method with Spring Data’s @Query
annotation.
Spring Data repositories usually extend from the Repository
or CrudRepository
interfaces.
If you use auto-configuration, the auto-configuration packages are searched for repositories.
The following example shows a typical Spring Data repository interface definition:
-
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?>?
}
We have barely scratched the surface of Spring Data R2DBC. For complete details, see the Spring Data R2DBC reference documentation.