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

Kotlin nativeなDBライブラリ Exposedを採用した話 / A story of adopting Exposed - a DB library written by Kotlin

Kotlin nativeなDBライブラリ Exposedを採用した話 / A story of adopting Exposed - a DB library written by Kotlin

C0084d908599d82cd7b001ea47cf3dd7?s=128

Yuya Urano

June 06, 2019
Tweet

Transcript

  1. Kotlin nativeなDBライブラリ
 Exposedを採用した話
 浦野 裕也 (@yu_rano)
 株式会社 日本経済新聞社 日経IDチーム


  2. 自己紹介
 2

  3. 3 浦野 裕也 (うらの ゆうや)
 @yu_rano
 
 所属 | 日本経済新聞社

    日経IDチーム 
 
 
 
日経IDのリニューアルプロジェクトでサーバーサイ ドの言語にKotlinを採用。
 今日はサーバーサイドの話をします。

  4. サーバーサイドで
 Kotlin使ってる人
 4

  5. DBライブラリの選定迷いませんか?
 5

  6. 各種ライブラリ 採用候補
 6 Application framework
 • Spring
 • Ktor
 Test


    • JUnit
 • Spek
 Database access
 • Spring JPA (Hibernate) 
 • MyBatis
 • DOMA2
 • Exposed

  7. Spring, JUnitはJava界の
 デファクト
 7

  8. 各種ライブラリ 採用候補
 8 Application framework
 • Spring (採用)
 • Ktor


    Test
 • JUnit (採用)
 • Spek
 Database access
 • Spring JPA (Hibernate) 
 • MyBatis
 • DOMA2
 • Exposed

  9. DBアクセスのデファクトは
 Hibernate?
 9

  10. 各種ライブラリ 採用候補
 10 Application framework
 • Spring (採用)
 • Ktor


    Test
 • JUnit (採用)
 • Spek
 Database access
 • Spring JPA (Hibernate) 
 • MyBatis
 • DOMA2
 • Exposed
 どれも決め手に欠ける... 

  11. なぜExposedを採用したか
 • 軽量なライブラリ
 • 異なるパラダイムの2つのAPI
 ◦ DSL API: SQLライクにかけるKotlin DSLのAPI


    ◦ DAO API: O/R mapper
 • 設定とデータアクセス処理がKotlinで完結する
 • ロードマップにコルーチンサポート・R2DBC/ADBAへの移行が載っていた
 ◦ 将来的にnon-blocking I/O モデルへの移行も視野に入れられそう
 ◦ https://github.com/JetBrains/Exposed/blob/master/ROADMAP.md
 • JetBrains製
 11
  12. 軽量なライブラリ
 mvnリポジトリにあるjarの容量
 698KB
 (version 0.13.7)
 
 参考| hibernate-core: 6.8MB (version

    5.4.3.Final) 
 12
  13. 異なるパラダイムのAPI
 DSL API
 型安全でSQLライクなsyntaxのDSL(ドメイン固有言語)
 生のSQLを書いているような感覚で書けるが、Kotlinベースなので静的型付けの恩恵を 受けられる。
 DAO API
 軽量なDAO(Data Access

    Object)を実現するAPI
 データアクセスのインターフェースを隠蔽してくれるため、SQLを書かずにデータアクセス を実装できる。
 13
  14. テーブル定義
 14 object StarWarsFilms : Table() { val id =

    integer("id").autoIncrement().primaryKey() val sequelId = integer("sequel_id").uniqueIndex() val name = varchar("name", 50) val director = varchar("director", 50) } 出典 | https://github.com/JetBrains/Exposed/wiki/DSL 
 Tableクラスを継承したobjectを定義する 
 • テーブル名はTable(name=”table_name”)で指定 
 • 指定しない場合、クラス名から”Table”サフィックスを取ったものになる 
 • 列名や型、PKなどの制約をメソッドチェーンで指定する 

  15. DSL APIの例
 fun main(args: Array<String>) { //an example connection to

    H2 DB Database.connect("jdbc:h2:mem:test", driver = "org.h2.Driver") transaction { // insert new city. SQL: INSERT INTO Cities (name) VALUES ('St. Petersburg') val stPeteId = Cities.insert { it[name] = "St. Petersburg" } get Cities.id // 'select *' SQL: SELECT Cities.id, Cities.name FROM Cities println("Cities: ${Cities.selectAll()}") } } object Cities: IntIdTable() { val name = varchar("name", 50) } 
 15 出典 | https://github.com/JetBrains/Exposed/wiki/Getting-Started

  16. DAO APIの例
 fun main(args: Array<String>) { //an example connection to

    H2 DB Database.connect("jdbc:h2:mem:test" , driver = "org.h2.Driver" ) transaction { // insert new city. SQL: INSERT INTO Cities (name) VALUES ('St. Petersburg') val stPete = City.new { name = "St. Petersburg" } // 'select *' SQL: SELECT Cities.id, Cities.name FROM Cities println("Cities: ${City.all()}") } } object Cities: IntIdTable() { val name = varchar("name", 50) } class City(id: EntityID<Int>) : IntEntity(id) { companion object : IntEntityClass <City>(Cities) var name by Cities.name } 
 16 出典 | https://github.com/JetBrains/Exposed/wiki/Getting-Started

  17. 設定とデータアクセス処理がKotlinで完結する
 Kotlinで完結することの利点:
 • DBアクセス部分のテストカバレッジが取りやすい
 • コード補完機能の恩恵を受けられる
 • Kotlinの型チェックの恩恵を受けられる
 
 17

  18. 実際使ってみてどうだったか?
 18

  19. • ライブラリのサイズが小さいため学習コストも小さい
 • コード補完の支援を受けながらクエリ書けるのが気持ちいい
 • 全てExposedで完結しようとせず、複雑なクエリは生のSQLを書くことも検討する
 ◦ Exposedで大抵のユースケースには対応できる
 ◦ CQRS(コマンドクエリ責務分離)の考え方に従ってモデルを分けて、複雑な参

    照系のみ生のSQLを使うと良さそう
 • DAO APIを使うとテーブル設計の制約が強くなるので、既存のデータベースを扱う 必要がある場合はDSL APIを推奨
 ◦ このあたりはHibernateなど他のO/R mapperと変わらない
 19
  20. 結論
 20

  21. サーバーサイドKotlin
 楽しい
 21

  22. ご清聴ありがとうございました
 22