Slide 1

Slide 1 text

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


Slide 2

Slide 2 text

自己紹介
 2

Slide 3

Slide 3 text

3 浦野 裕也 (うらの ゆうや)
 @yu_rano
 
 所属 | 日本経済新聞社 日経IDチーム 
 
 
 
日経IDのリニューアルプロジェクトでサーバーサイ ドの言語にKotlinを採用。
 今日はサーバーサイドの話をします。


Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

各種ライブラリ 採用候補
 6 Application framework
 ● Spring
 ● Ktor
 Test
 ● JUnit
 ● Spek
 Database access
 ● Spring JPA (Hibernate) 
 ● MyBatis
 ● DOMA2
 ● Exposed


Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

各種ライブラリ 採用候補
 8 Application framework
 ● Spring (採用)
 ● Ktor
 Test
 ● JUnit (採用)
 ● Spek
 Database access
 ● Spring JPA (Hibernate) 
 ● MyBatis
 ● DOMA2
 ● Exposed


Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

各種ライブラリ 採用候補
 10 Application framework
 ● Spring (採用)
 ● Ktor
 Test
 ● JUnit (採用)
 ● Spek
 Database access
 ● Spring JPA (Hibernate) 
 ● MyBatis
 ● DOMA2
 ● Exposed
 どれも決め手に欠ける... 


Slide 11

Slide 11 text

なぜ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

Slide 12

Slide 12 text

軽量なライブラリ
 mvnリポジトリにあるjarの容量
 698KB
 (version 0.13.7)
 
 参考| hibernate-core: 6.8MB (version 5.4.3.Final) 
 12

Slide 13

Slide 13 text

異なるパラダイムのAPI
 DSL API
 型安全でSQLライクなsyntaxのDSL(ドメイン固有言語)
 生のSQLを書いているような感覚で書けるが、Kotlinベースなので静的型付けの恩恵を 受けられる。
 DAO API
 軽量なDAO(Data Access Object)を実現するAPI
 データアクセスのインターフェースを隠蔽してくれるため、SQLを書かずにデータアクセス を実装できる。
 13

Slide 14

Slide 14 text

テーブル定義
 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などの制約をメソッドチェーンで指定する 


Slide 15

Slide 15 text

DSL APIの例
 fun main(args: Array) { //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


Slide 16

Slide 16 text

DAO APIの例
 fun main(args: Array) { //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) : IntEntity(id) { companion object : IntEntityClass (Cities) var name by Cities.name } 
 16 出典 | https://github.com/JetBrains/Exposed/wiki/Getting-Started


Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

● ライブラリのサイズが小さいため学習コストも小さい
 ● コード補完の支援を受けながらクエリ書けるのが気持ちいい
 ● 全てExposedで完結しようとせず、複雑なクエリは生のSQLを書くことも検討する
 ○ Exposedで大抵のユースケースには対応できる
 ○ CQRS(コマンドクエリ責務分離)の考え方に従ってモデルを分けて、複雑な参 照系のみ生のSQLを使うと良さそう
 ● DAO APIを使うとテーブル設計の制約が強くなるので、既存のデータベースを扱う 必要がある場合はDSL APIを推奨
 ○ このあたりはHibernateなど他のO/R mapperと変わらない
 19

Slide 20

Slide 20 text

結論
 20

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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