Hello R2DBC

## R2DBC?

https://r2dbc.io/

Spring One Platform 2018で発表されたリレーショナルデータベース用のリアクティブプログラミングAPI。みんなが待ってるやつ。

2016年頃からのSpring5を中心にしてWebやNoSQL周りはリアクティブ対応をしてきてるんだけど、RDBMSJDBCブロッキングなので対応できてなくて、そこが必要よなーってみんな待ってる。

R2DBCのビデオ見たんだけど本番では絶対使わないでねって言ってた。んで、R2DBCのゴールはADBA (Asynchronous Database Access API)のSpecに良い影響を与えること。ほほー。

## 今日の目標

ということで、現時点でPostgreSQL用のr2dbc-postgresqlがあるから、今日はそれでSelectくらいやってみようかな。Repositoryは作らずに直接SQL書く感じで。

コードはここ。

https://github.com/bufferings/hello-r2dbc/tree/20181117

## 注意点

WebFluxのMonoやFluxの扱いも、R2DBCの扱いも、全然良くわかってないので間違ったこと書いてるかも。ここで書いてることを鵜呑みにせずに自分で確かめてください。

## PostgreSQLの用意

Docker ComposeでPostgreSQLを用意。

version: "2"

services:
  db:
    image: postgres:11-alpine
    environment:
      POSTGRES_PASSWORD: mysecretpassword 
    ports:
      - 5432:5432
    volumes:
      - ./initdb.d:/docker-entrypoint-initdb.d

初期データはこんな感じで適当にPostgreSQLのTutorial (https://www.postgresql.org/docs/11/tutorial-table.html)から持ってきた。

CREATE TABLE weather (
    city            varchar(80),
    temp_lo         int,           -- low temperature
    temp_hi         int,           -- high temperature
    prcp            real,          -- precipitation
    date            date
);

CREATE TABLE cities (
    name            varchar(80),
    location        point
);

INSERT INTO weather (city, temp_lo, temp_hi, prcp, date) VALUES 
  ('San Francisco', 46, 50, 0.25, '1994-11-26'),
  ('San Francisco', 46, 50, 0.25, '1994-11-27'),
  ('San Francisco', 46, 50, 0.25, '1994-11-28'),
  ('San Francisco', 46, 50, 0.25, '1994-11-29');

## pom.xml

さて。SpringBoot 2.1.0.RELEASE + Reactive Webでプロジェクトを作って、そこにR2DBCのDependencyを追加。r2dbc-clientも使いたかったので追加。

        <dependency>
            <groupId>io.r2dbc</groupId>
            <artifactId>r2dbc-postgresql</artifactId>
            <version>1.0.0.BUILD-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>io.r2dbc</groupId>
            <artifactId>r2dbc-client</artifactId>
            <version>1.0.0.BUILD-SNAPSHOT</version>
        </dependency>

SnapshotとかMilestoneバージョンを使うからリポジトリーも追加。

    <repositories>
        <repository>
            <id>spring-snapshots</id>
            <name>Spring Snapshots</name>
            <url>https://repo.spring.io/snapshot</url>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>

ConnectionFactory

こんな感じっぽい。

  private PostgresqlConnectionFactory getPostgresqlConnectionFactory() {
    var configuration = PostgresqlConnectionConfiguration.builder()
        .host("localhost")
        .database("postgres")
        .username("postgres")
        .password("mysecretpassword")
        .build();
    return new PostgresqlConnectionFactory(configuration);
  }

このFactoryから直接ごにょごにょやってSQLを発行してもいいんだけど、もうちょっと分かりやすく書けるR2dbcっていうクライアントがあるからそっちを使ってみた。

  private Flux<String> hello() {
    var connectionFactory = getPostgresqlConnectionFactory();
    var r2dbc = new R2dbc(connectionFactory);
    return r2dbc.inTransaction(h ->
        h.select("SELECT city, temp_lo, temp_hi, prcp, date FROM weather")
            .mapRow(row -> row.get("city", String.class)));
  }

んで、それをマッピング

  @Bean
  RouterFunction<ServerResponse> getRoute() {
    return route(GET("/"),
        req -> ok().body(hello(), String.class));
  }

## 実行

(cd db; docker-compose up -d)
Creating network "db_default" with the default driver
Creating db_db_1_d69d7879eaa0 ... done(cd demo-webflux-r2dbc; ./mvnw spring-boot:run)
(中略)
2018-11-17 20:59:32.474  INFO 25588 --- [           main] o.s.b.web.embedded.netty.NettyWebServer  : Netty started on port(s): 8080
2018-11-17 20:59:32.479  INFO 25588 --- [           main] c.e.d.DemoWebfluxR2dbcApplication        : Started DemoWebfluxR2dbcApplication in 2.047 seconds (JVM running for 5.796)

叩いてみる。

❯ curl localhost:8080
San FranciscoSan FranciscoSan FranciscoSan Francisco

んー。とりあえず動いてるっぽい。満足。

## TODO

そもそも、MonoとFluxの使い方をそろそろちゃんと勉強しておいたほうが良さそう。それからr2dbc-clientやspring-data-r2dbcあたりを触りたいなー。