## R2DBC?
Spring One Platform 2018で発表されたリレーショナルデータベース用のリアクティブプログラミングAPI。みんなが待ってるやつ。
2016年頃からのSpring5を中心にしてWebやNoSQL周りはリアクティブ対応をしてきてるんだけど、RDBMSはJDBCがブロッキングなので対応できてなくて、そこが必要よなーってみんな待ってる。
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あたりを触りたいなー。