入門

啟動一個工作環境的簡單方法是在 Spring Tools 中或透過 Spring Initializr 建立一個 Spring 專案。

首先,你需要設定並執行資料庫伺服器。關於如何配置資料庫以進行 R2DBC 訪問,請參考你的資料庫供應商文件。

要求

Spring Data R2DBC 需要 Spring Framework 6.2.6 及更高版本。

資料庫方面,Spring Data R2DBC 需要一個 驅動程式 來抽象通用 SQL 功能,使其不受特定供應商差異的影響。Spring Data R2DBC 直接支援以下資料庫:

如果你使用不同的資料庫,你的應用程式將無法啟動。方言 章節包含有關在這種情況下如何操作的更多詳細資訊。

Hello World

在 STS 中建立一個 Spring 專案

  1. 前往 File → New → Spring Template Project → Simple Spring Utility Project,並在提示時按 Yes。然後輸入專案和包名稱,例如 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.5</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.6</spring.version>
  5. 將 Maven 的 Spring Milestone 倉庫地址新增到你的 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 方法。

  • 如果建構函式引數名稱與儲存行中的列名匹配,則它們用於例項化物件。

示例 Repository

有一個包含多個示例的 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,這是資料庫互動和 Repository 實現所必需的。

方言

Spring Data R2DBC 使用 Dialect 來封裝特定於資料庫或其驅動程式的行為。Spring Data R2DBC 透過檢查 ConnectionFactory 並相應地選擇合適的資料庫方言來應對資料庫的特定性。如果你使用的資料庫沒有可用的方言,那麼你的應用程式將無法啟動。在這種情況下,你必須請你的供應商提供一個 Dialect 實現。或者,你可以實現自己的 Dialect

方言由 DialectResolverConnectionFactory 解析,通常透過檢查 ConnectionFactoryMetadata 來實現。 + 你可以透過註冊一個實現 org.springframework.data.r2dbc.dialect.DialectResolver$R2dbcDialectProvider 的類,並透過 META-INF/spring.factories 檔案,讓 Spring 自動發現你的 R2dbcDialectDialectResolver 使用 Spring 的 SpringFactoriesLoader 從類路徑中發現方言提供者實現。為此

  1. 實現你自己的 Dialect

  2. 實現一個 R2dbcDialectProvider 返回 Dialect

  3. 透過在 META-INF 下建立一個 spring.factories 資源,並新增一行來註冊提供者
    org.springframework.data.r2dbc.dialect.DialectResolver$R2dbcDialectProvider=<fully qualified name of your R2dbcDialectProvider>