Upgrade to Pro — share decks privately, control downloads, hide ads and more …

R2DBCをサポートするORM Komapper

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.

R2DBCをサポートするORM Komapper

R2DBCをサポートするORM Komapper

Avatar for Toshihiro Nakamura

Toshihiro Nakamura

April 15, 2022
Tweet

More Decks by Toshihiro Nakamura

Other Decks in Technology

Transcript

  1. R2DBCとは データベースアクセスのためのリアクティブなAPI • R2DBC = Reactive Relational Database Connectivity データベース

    R2DBC ドライバ ORMライブラリ アプリケーション R2DBC API ノンブロッキングIO Komapper Spring Data R2DBC JOOQ リアクティブなAPI 広義のORMライブラリ • 効率的 • スケールしやすい • ノンブロッキングIOと 相性が良い
  2. R2DBCのリアクティブなAPIの利⽤例 ConnectionFactory connectionFactory = ConnectionFactories .get("r2dbc:h2:mem:///testdb"); Mono.from(connectionFactory.create()) .flatMapMany(connection -> connection

    .createStatement("SELECT firstname FROM PERSON WHERE age > $1") .bind("$1", 42) .execute()) .flatMap(result -> result .map((row, rowMetadata) -> row.get("firstname", String.class))) .doOnNext(System.out::println) .subscribe(); R2DBCサイトに掲載のサンプルコード(Javaコード) リアクティブなAPIは難しい
  3. Komapperのコード例|JDBC接続とR2DBC接続で共通のコード @KomapperEntity data class Employee( @KomapperId @KomapperAutoIncrement val id: Int,

    val name: String ) create table employee ( id integer generated always as identity not null, name varchar(500) not null, constraint pk_employee primary key(id) ) 従業員テーブル 従業員クラス(Kotlinコード)
  4. Komapperのコード例|JDBC接続の場合 // ①データベースインスタンスの作成 val db = JdbcDatabase(“jdbc:h2:mem:test;DB_CLOSE_DELAY=-1”) // ②名前で従業員⼀覧を取得するクエリの構築 val

    e = Meta.employee val query: Query<List<Employee>> = QueryDsl.from(e).where { e.name eq "ABC" }.orderBy(e.id) fun main() { // ③クエリの実⾏ val employees : List<Employee> = db.runQuery(query) } select t0_.id, t0_.name from employee as t0_ where t0_.name = ? order by t0_.id asc Kotlinコード 発⾏されるSQL
  5. Komapperのコード例|R2DBC接続の場合 // ①データベースインスタンスの作成 val db = R2dbcDatabase(“r2dbc:h2:mem:///test;DB_CLOSE_DELAY=-1”) // ②名前で従業員⼀覧を取得するクエリの構築 val

    e = Meta.employee val query: Query<List<Employee>> = QueryDsl.from(e).where { e.name eq "ABC" }.orderBy(e.id) suspend fun main() { // ③クエリの実⾏ val employees : List<Employee> = db.runQuery(query) } select t0_.id, t0_.name from employee as t0_ where t0_.name = ? order by t0_.id asc Kotlinコード 発⾏されるSQL
  6. Komapperのコード例|JDBC接続とR2DBC接続の⽐較 違いはごくわずか • データベースのインスタンスが違う • R2DBC接続ではrunQueryをsuspend関数内で呼び出す val db = JdbcDatabase(“jdbc:h2:mem:test;DB_CLOSE_DELAY=-1”)

    val e = Meta.employee val query = QueryDsl.from(e).where { e.name eq "ABC" }.orderBy(e.id) fun main() { val employees = db.runQuery(query) } val db = R2dbcDatabase(“r2dbc:h2:mem:///test;DB_CLOSE_DELAY=-1”) val e = Meta.employee val query = QueryDsl.from(e).where { e.name eq "ABC" }.orderBy(e.id) suspend fun main() { val employees = db.runQuery(query) } JDBC接続 R2DBC接続 接続⽂字列は⽐較対象にしていません
  7. Komapperの特徴のまとめ|その2 R2DBC版にはリアクティブ特有の処理が出てこない • リアクティブな処理をコルーチンに変換している • リアクティブなAPIの難しさを低減させている ConnectionFactory connectionFactory = ConnectionFactories

    .get("r2dbc:h2:mem:///testdb"); Mono.from(connectionFactory.create()) .flatMapMany(connection -> connection .createStatement("SELECT firstname FROM PERSON WHERE age > $1") .bind("$1", 42) .execute()) .flatMap(result -> result .map((row, rowMetadata) -> row.get("firstname", String.class))) .doOnNext(System.out::println) .subscribe(); 再掲のJavaコード。Komapperでは⻘字のようなリアクティブ特有の処理が不要
  8. 主要フレームワークとの連携|Spring Framework JDBCとR2DBCのどちらもサポート • JDBC版はWeb MVC、R2DBC版はWebFluxと組みわせるのがオススメ @RestController @Transactional class MyController(private

    val db: JdbcDatabase) { @RequestMapping("/") fun list(): List<Employee> { val e = Meta.employee val query = QueryDsl.from(e).orderBy(e.id) return db.runQuery(query) } } Komapper JDBC + Spring Web MVC @RestController @Transactional class MyController(private val db: R2dbcDatabase) { @RequestMapping("/") suspend fun list(): List<Employee> { val e = Meta.employee val query = QueryDsl.from(e).orderBy(e.id) return db.runQuery(query) } } Komapper R2DBC + Spring WebFlux
  9. 主要フレームワークとの連携|Ktor R2DBCをサポート • Ktorの⾮同期プログラミングモデルと相性が良い val db = R2dbcDatabase("r2dbc:h2:mem:///example;DB_CLOSE_DELAY=-1") fun Application.configureRouting()

    { routing { get("/") { val e = Meta.employee val query = QueryDsl.from(e).orderBy(e.id) db.withTransaction { val employees = db.runQuery(query) call.respond(employees) } } } } Komapper R2DBC + Ktor 2.0
  10. Komapperのこれから 現時点でv0.32.0が最新 R2DBC 0.9.1を利⽤ 5⽉上旬 v1.0-betaリリース R2DBC 1.0に対応 5⽉下旬 v1.0リリース

    R2DBCドライバの対応状況次第では遅れる可能性があります v1.0を5⽉にリリース予定
  11. 参考情報 Komapper • https://www.komapper.org/ • Webサイト • https://github.com/komapper/komapper-examples • Spring

    Boot、Ktor、Quarkusのサンプルアプリ R2DBC • https://r2dbc.io/ • Webサイト • https://r2dbc.io/spec/0.9.1.RELEASE/spec/html/ • R2DBCの仕様