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

R2DBCをサポートするORM Komapper

R2DBCをサポートするORM Komapper

R2DBCをサポートするORM Komapper

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の仕様