入门指南

一种轻松启动工作环境的方法是在 Spring ToolsSpring Initializr 中创建一个基于 Spring 的项目。

首先,您需要设置一个正在运行的数据库服务器。请参阅您的供应商文档,了解如何配置数据库以进行 R2DBC 访问。

需求

Spring Data R2DBC 要求 Spring Framework 6.2.0 及更高版本。

在数据库方面,Spring Data R2DBC 需要一个 驱动程序 来抽象跨供应商特定风格的通用 SQL 功能。Spring Data R2DBC 直接支持以下数据库:

如果您使用的是其他数据库,则您的应用程序将无法启动。方言 部分包含有关在这种情况下如何继续的更多详细信息。

Hello World

在 STS 中创建 Spring 项目:

  1. 转到 文件 → 新建 → Spring 模板项目 → 简单 Spring 实用程序项目,并在出现提示时按“是”。然后输入项目和包名称,例如 org.spring.r2dbc.example

  2. 将以下内容添加到 pom.xml 文件的 dependencies 元素中

  3. 将以下内容添加到 pom.xml 文件的 dependencies 元素中

    <dependencies>
    
      <!-- other dependency elements omitted -->
    
      <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-r2dbc</artifactId>
        <version>3.4.0</version>
      </dependency>
    
      <!-- a R2DBC driver -->
      <dependency>
        <groupId>io.r2dbc</groupId>
        <artifactId>r2dbc-h2</artifactId>
        <version>x.y.z</version>
      </dependency>
    
    </dependencies>
  4. 将 pom.xml 中 Spring 的版本更改为:

    <spring.version>6.2.0</spring.version>
  5. 将以下 Spring 里程碑存储库位置添加到您的 pom.xml 中,使其与您的 <dependencies/> 元素位于同一级别

    <repositories>
      <repository>
        <id>spring-milestone</id>
        <name>Spring Maven MILESTONE Repository</name>
        <url>https://repo.spring.io/milestone</url>
      </repository>
    </repositories>

此存储库也可以 在此处浏览

您可能还希望将日志级别设置为 DEBUG 以查看更多信息。为此,请编辑 application.properties 文件,使其包含以下内容:

logging.level.org.springframework.r2dbc=DEBUG

然后,您可以例如创建一个要持久化的 Person 类,如下所示:

public class Person {

	private final String id;
	private final String name;
	private final int age;

	public Person(String id, String name, int age) {
		this.id = id;
		this.name = name;
		this.age = age;
	}

	public String getId() {
		return id;
	}

	public String getName() {
		return name;
	}

	public int getAge() {
		return age;
	}

	@Override
	public String toString() {
		return "Person [id=" + id + ", name=" + name + ", age=" + age + "]";
	}
}

接下来,您需要在您的数据库中创建一个表结构,如下所示:

CREATE TABLE person
  (id VARCHAR(255) PRIMARY KEY,
   name VARCHAR(255),
   age INT);

您还需要一个要运行的主应用程序,如下所示:

import io.r2dbc.spi.ConnectionFactories;
import io.r2dbc.spi.ConnectionFactory;
import reactor.test.StepVerifier;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.data.r2dbc.core.R2dbcEntityTemplate;

public class R2dbcApp {

  private static final Log log = LogFactory.getLog(R2dbcApp.class);

  public static void main(String[] args) {

    ConnectionFactory connectionFactory = ConnectionFactories.get("r2dbc:h2:mem:///test?options=DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE");

    R2dbcEntityTemplate template = new R2dbcEntityTemplate(connectionFactory);

    template.getDatabaseClient().sql("CREATE TABLE person" +
        "(id VARCHAR(255) PRIMARY KEY," +
        "name VARCHAR(255)," +
        "age INT)")
      .fetch()
      .rowsUpdated()
      .as(StepVerifier::create)
      .expectNextCount(1)
      .verifyComplete();

    template.insert(Person.class)
      .using(new Person("joe", "Joe", 34))
      .as(StepVerifier::create)
      .expectNextCount(1)
      .verifyComplete();

    template.select(Person.class)
      .first()
      .doOnNext(it -> log.info(it))
      .as(StepVerifier::create)
      .expectNextCount(1)
      .verifyComplete();
  }
}

运行主程序时,前面的示例会产生类似于以下的输出:

2018-11-28 10:47:03,893 DEBUG amework.core.r2dbc.DefaultDatabaseClient: 310 - Executing SQL statement [CREATE TABLE person
  (id VARCHAR(255) PRIMARY KEY,
   name VARCHAR(255),
   age INT)]
2018-11-28 10:47:04,074 DEBUG amework.core.r2dbc.DefaultDatabaseClient: 908 - Executing SQL statement [INSERT INTO person (id, name, age) VALUES($1, $2, $3)]
2018-11-28 10:47:04,092 DEBUG amework.core.r2dbc.DefaultDatabaseClient: 575 - Executing SQL statement [SELECT id, name, age FROM person]
2018-11-28 10:47:04,436  INFO        org.spring.r2dbc.example.R2dbcApp:  43 - Person [id='joe', name='Joe', age=34]

即使在这个简单的示例中,也有一些需要注意的地方:

  • 您可以使用标准 io.r2dbc.spi.ConnectionFactory 对象,在 Spring Data R2DBC 中创建中心辅助类 (R2dbcEntityTemplate) 的实例。

  • 映射器针对标准 POJO 对象工作,无需任何其他元数据(尽管您可以选择提供该信息,请参阅 此处)。

  • 映射约定可以使用字段访问。请注意,Person 类只有 getter 方法。

  • 如果构造函数参数名称与存储行的列名称匹配,则使用它们来实例化对象。

示例仓库

有一个 包含多个示例的 GitHub 仓库,您可以下载并试用这些示例,以了解该库的工作原理。

使用 Spring 连接到关系数据库

使用关系数据库和 Spring 时,首要任务之一是使用 IoC 容器创建 io.r2dbc.spi.ConnectionFactory 对象。确保使用 受支持的数据库和驱动程序

使用 Java 配置注册 ConnectionFactory 实例

以下示例显示了使用基于 Java 的 bean 元数据来注册 io.r2dbc.spi.ConnectionFactory 实例的示例:

使用 Java 配置注册 io.r2dbc.spi.ConnectionFactory 对象
@Configuration
public class ApplicationConfiguration extends AbstractR2dbcConfiguration {

  @Override
  @Bean
  public ConnectionFactory connectionFactory() {
    return …
  }
}

这种方法允许您使用标准 io.r2dbc.spi.ConnectionFactory 实例,容器使用 Spring 的 AbstractR2dbcConfiguration。与直接注册 ConnectionFactory 实例相比,配置支持还具有额外优势,即还为容器提供 ExceptionTranslator 实现,该实现将 R2DBC 异常转换为 Spring 可移植的 DataAccessException 层次结构中的异常,用于使用 @Repository 注解的数据访问类。此层次结构和 @Repository 的使用在 Spring 的 DAO 支持功能 中进行了描述。

AbstractR2dbcConfiguration 还注册 DatabaseClient,这是数据库交互和仓库实现所必需的。

方言

Spring Data R2DBC 使用 Dialect 来封装特定于数据库或其驱动程序的行为。Spring Data R2DBC 通过检查 ConnectionFactory 并相应地选择合适的数据库方言来对数据库的细节做出反应。如果您使用的是没有方言的数据库,则您的应用程序将无法启动。在这种情况下,您必须要求您的供应商提供 Dialect 实现。或者,您可以自己实现 Dialect

方言由 DialectResolverConnectionFactory 解析,通常通过检查 ConnectionFactoryMetadata。您可以让 Spring 自动发现您的 R2dbcDialect,方法是通过 META-INF/spring.factories 注册实现 org.springframework.data.r2dbc.dialect.DialectResolver$R2dbcDialectProvider 的类。DialectResolver 使用 Spring 的 SpringFactoriesLoader 从类路径中发现方言提供程序实现。为此:

  1. 实现您自己的 Dialect

  2. 实现一个返回DialectR2dbcDialectProvider

  3. 通过在META-INF下创建一个spring.factories资源来注册提供程序,并通过添加一行进行注册:
    org.springframework.data.r2dbc.dialect.DialectResolver$R2dbcDialectProvider=<你的R2dbcDialectProvider的全限定名>