Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
「2024年版 Kotlin サーバーサイドプログラミング実践開発」の補講 〜O/Rマッパー編〜
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Takehata Naoto
July 18, 2024
Programming
2
790
「2024年版 Kotlin サーバーサイドプログラミング実践開発」の補講 〜O/Rマッパー編〜
2024年7月18日(土) 「Server-side Kotlin Night 2024/07」の発表資料です。
Takehata Naoto
July 18, 2024
Tweet
Share
More Decks by Takehata Naoto
See All by Takehata Naoto
AI時代でも変わらない技術コミュニティの力~10年続く“ゆるい”つながりが生み出す価値
n_takehata
2
620
KotlinConf 2025で発表された言語のアップデートと現地参加レポート
n_takehata
2
360
KotlinConf 2025 現地で感じたServer-Side Kotlin
n_takehata
2
420
KotlinConf 2025 現地参加の土産話
n_takehata
0
190
組織貢献をするフリーランスエンジニアという生き方
n_takehata
1
5.8k
2024年版 Kotlin サーバーサイドプログラミング実践開発
n_takehata
9
8.6k
Server-Side目線で見る、Kotlin Festの楽しみ方
n_takehata
0
590
KotlinとCloud Vision APIで領収書の電子帳簿保存法対応をする
n_takehata
1
1.8k
KotlinConf 2023 現地参加レポート
n_takehata
1
400
Other Decks in Programming
See All in Programming
浮動小数の比較について
kishikawakatsumi
0
370
What Spring Developers Should Know About Jakarta EE
ivargrimstad
0
190
手戻りゼロ? Spec Driven Developmentとは@KAG AI week
tmhirai
1
160
Go1.26 go fixをプロダクトに適用して困ったこと
kurakura0916
0
320
Claude Code、ちょっとした工夫で開発体験が変わる
tigertora7571
0
200
ベクトル検索のフィルタを用いた機械学習モデルとの統合 / python-meetup-fukuoka-06-vector-attr
monochromegane
2
290
CSC307 Lecture 12
javiergs
PRO
0
460
あなたはユーザーではない #PdENight
kajitack
4
300
ふつうの Rubyist、ちいさなデバイス、大きな一年
bash0c7
0
110
The Past, Present, and Future of Enterprise Java
ivargrimstad
0
200
API Platformを活用したPHPによる本格的なWeb API開発 / api-platform-book-intro
ttskch
1
120
Railsの気持ちを考えながらコントローラとビューを整頓する/tidying-rails-controllers-and-views-as-rails-think
moro
4
370
Featured
See All Featured
For a Future-Friendly Web
brad_frost
183
10k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
666
130k
Dominate Local Search Results - an insider guide to GBP, reviews, and Local SEO
greggifford
PRO
0
93
Avoiding the “Bad Training, Faster” Trap in the Age of AI
tmiket
0
96
Thoughts on Productivity
jonyablonski
75
5.1k
Digital Projects Gone Horribly Wrong (And the UX Pros Who Still Save the Day) - Dean Schuster
uxyall
0
590
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
128
55k
Agile Leadership in an Agile Organization
kimpetersen
PRO
0
97
The Curse of the Amulet
leimatthew05
1
9.5k
Agile that works and the tools we love
rasmusluckow
331
21k
AI Search: Implications for SEO and How to Move Forward - #ShenzhenSEOConference
aleyda
1
1.1k
Getting science done with accelerated Python computing platforms
jacobtomlinson
2
130
Transcript
「2024年版 Kotlin サーバーサイドプログラミング 実践開発」の補講 〜O/Rマッパー編〜 2024年7月18日 Server-side Kotlin Night 2024/07
竹端 尚人
自己紹介
竹端 尚人 主にバックエンドエンジニア Twitter: @n_takehata • 2006.04〜 公務員 • 2007.12〜
SES • 2011.04〜 モバイルゲーム開発(サーバーサイド Kotlinを始める) • 2020.12〜 フリーランス(バックエンド開発、 テックリード、技術顧問など) 概要 現在は主に、クラウド型電子カルテを開発している株式 会社ヘンリーでエンジニアとして従事 Kotlin愛好会というコミュニティの運営もやっています
Kotlin愛好会も明日やります!
• CEDEC 2018、2019登壇 • Software Design 2019年2月号〜4月号で短期連載 「サーバーサイド開発の品質を向上させる Java→Kotlin移行のススメ」執筆 •
2021年4月 書籍「Kotlin サーバーサイドプログラ ミング実践開発」出版 • 2023年4月 Techpitにて「Kotlin入門ガイドー言語 思想から特徴・歴史・使いどころまで、まるっと予 備知識がわかる教科書」執筆 • Kotlin Fest 2024登壇 登壇、執筆
2024年版 Kotlin サーバーサイドプログラミング実践開発
Kotlin Fest 2024で話した内容から、 盛り上がったO/Rマッパーについて深堀って話します
Kotlin Fest 2024の発表資料はこちら https://speakerdeck.com/n_takehata/kotlin-s erver-side-programming-practice-2024
アジェンダ 1. Kotlin Fest 2024の振り返り 2. 各種O/Rマッパーのおさらい 3. 色々なSQLを実装してみる 4.
まとめ
アジェンダ 1. Kotlin Fest 2024の振り返り 2. 各種O/Rマッパーのおさらい 3. 色々なSQLを実装してみる 4.
まとめ
1. Kotlin Fest 2024の振り返り
「2024年版 Kotlin サーバーサイドプログラミング 実践開発」 の内容
• 「Kotlin サーバーサイドプログラミング実践開発」の 内容紹介 • 現在のサーバーサイドKotlinで使えるフレームワークの 紹介(Web、DI、O/Rマッパー、テスト) • 今Kotlinでアプリケーションを作る場合のフレームワー ク選定の紹介
「2024年版 Kotlin サーバーサイドプログラミング 実践開発」 の内容
• Ktor(Webアプリケーションフレームワーク) • Koin(DIフレームワーク) • JOOQ(O/Rマッパー) • Kotest(テストフレームワーク)
RepositoryImpl O/Rマッパー (JOOQ) ドメイン オブジェクト Repository Test (Kotest) Service Controller
(Ktor) DI(Koin)
Ask the Speaker、懇親会で O/Rマッパーの話で盛り上がった
• セッションでも「O/Rマッパーが一番迷った」と話して いた • 「O/Rマッパーだけは何使おうか迷うんですよね」とい う悩みが多かった • SQLに近い形で書ける方がいいという意見に「やっぱ りそうですよね」というリアクション O/Rマッパーの話で盛り上がった
結局エンジニアはSQLを書きたい(人が多い)
なぜエンジニアはSQLを書きたいのか?
• 結局「こういうSQLを書きたいからコードは・・・」 という順序で考えている • テーブル設計を意識してデータを扱うのに、SQLだけ 抽象化しても混乱する • テーブルもSQLも意識せず「こういうデータが欲し い」を考えるだけにできないと抽象化の意味がない なぜエンジニアはSQLを書きたいのか?
結局エンジニアはSQLを書きたい(人が多い) 書きたいわけではないけど、いい具合に抽象化された ソリューションがない?
今回は各種O/Rマッパーで色々なSQLの 実装方法を紹介します
参考: Kotlin Fest 2024登壇の振り返り(ブログ) https://blog.takehata-engineer.com/entry/loo k-back-at-kotlin-fest-2024
アジェンダ 1. Kotlin Fest 2024の振り返り 2. 各種O/Rマッパーのおさらい 3. 色々なSQLを実装してみる 4.
まとめ
2. 各種O/Rマッパーのおさらい
• Exposed • JOOQ • Ktorm Kotlin Fest 2024で紹介したO/Rマッパー
Exposed
• JetBrains社が開発しているKotlin製のO/Rマッパー • SQLライクに実装できるDSL、軽量なDAOという2つの アクセス方法が用意されている • 長い間0.x系が続いていたが、2024年中に1.0になるこ とが予定されている Exposedとは?
JOOQ
• SQLに近いDSLでのクエリ作成が可能 • テーブルスキーマからのコード生成が可能で、もとも とJavaのO/RマッパーだがKotlinのコード生成にも対応 している • R2DBCによるノンブロッキングI/Oにも対応 JOOQとは?
Ktorm
• 純粋なJDBCに基づいたKotlin用の軽量なO/Rマッパー • Kotlin製のサードパーティフレームワーク • 生のSQLに近い形で書ける柔軟なDSLが用意されている Ktormとは?
Kotlin Fest 2024では紹介しなかった その他のO/Rマッパー
• MyBatis • Doma2 • Komapper その他のO/Rマッパー
アジェンダ 1. Kotlin Fest 2024の振り返り 2. 各種O/Rマッパーのおさらい 3. 色々なSQLを実装してみる 4.
まとめ
3. 色々なSQLを実装してみる
• Exposed • JOOQ • Ktorm ※ExposedはSQL DSLを使用します この3つのO/Rマッパーで色々なクエリを書いて 比較していきます
使用するテーブル(RDBはMySQLを使用) CREATE TABLE users ( id varchar(10) NOT NULL, name
varchar(50) NOT NULL, age int NOT NULL, PRIMARY KEY (id) ); CREATE TABLE user_purchase_histories ( id varchar(10) NOT NULL, user_id varchar(10) NOT NULL, purchase_date date NOT NULL, price int NOT NULL, PRIMARY KEY (id) );
基本的なCRUDのクエリ (Kotlin Festからの再掲)
transaction { // Insert Users.insert { it[id] = "kotlin" it[name]
= "Kotlin Fest" it[age] = 3 } // Update Users.update({ Users.id eq "kotlin" }) { it[age] = 4 } // Select val users = Users.select(Users.name, Users.age).where { Users.age greaterEq 3 } // Delete Users.deleteWhere{ id eq "kotlin" } } Exposed
// Insert dslContext.insertInto(USERS) .columns(USERS.ID, USERS.NAME, USERS.AGE) .values("kotlin", "Kotlin Fest", 3)
.execute() // Update dslContext.update(USERS) .set(USERS.AGE, 4) .where(USERS.ID.eq("kotlin")) .execute() // Select val users = dslContext.selectFrom(USERS).where(USERS.AGE.ge(3)).fetch() // Delete dslContext.deleteFrom(USERS) .where(USERS.ID.eq("kotlin")) .execute() JOOQ
// Insert database.insert(Users) { set(it.id, "kotlin") set(it.name, "Kotlin Fest" )
set(it.age, 3) } // Update database.update(Users) { set(it.age, 4) where { it.id eq "kotlin" } } // Select val users = database.from(Users).select().where { Users.age greaterEq 3 } // Delete database.delete(Users) { it.id eq "kotlin" } Ktorm
• Exposedはfromやupdate文のsetなど、キーワードを 削って抽象化している • JOOQはほぼ生のSQLと同じ構文で書ける • Ktormも生のSQLに近いが、fromの位置やinsertで使 うsetキーワードなど、少し差分がある
GROUP BY、ORDER BY、LIMIT、OFFSET
select age, count(*) from USERS group by age order by
count(*) desc limit 3 offset 1;
Users.select(Users.age, Users.id.count()) .groupBy(Users.age) .orderBy(Users.id.count(), SortOrder.DESC) .limit(3, offset = 1) Exposed
dslContext.select(USERS.AGE, count()) .from(USERS) .groupBy(USERS.AGE) .orderBy(count().desc()) .limit(1, 3) .fetch() JOOQ
dslContext.select(USERS.AGE, count()) .from(USERS) .groupBy(USERS.AGE) .orderBy(count().desc()) .limit(3) .offset(1) .fetch() offsetを別で渡すことも可能
database.from(Users) .select(Users.age, count()) .groupBy(Users.age) .orderBy(count().desc()) .limit(1, 3) Ktorm
database.from(Users) .select(Users.age, count()) .groupBy(Users.age) .orderBy(count().desc()) .limit(3) .offset(1) off offsetを別で渡すことも可能
• 3つとも書き方に大きな差分はない • ExposedがFromがない分短いくらい
JOIN
select * from USERS left join USER_PURCHASE_HISTORIES on USERS.id =
USER_PURCHASE_HISTORIES.user_id;
Users.leftJoin( UserPurchaseHistories , { Users.id }, { UserPurchaseHistories.userId } ).selectAll()
Exposed
dslContext.select() .from(USERS) .leftJoin(USER_PURCHASE_HISTORIES) .on(USERS.ID.eq(USER_PURCHASE_HISTORIES.USER_ID)) .fetch() JOOQ
database .from(Users) .leftJoin( UserPurchaseHistories , on = Users.id eq UserPurchaseHistories.userId)
.select() Ktorm
• Exposedはonのキーワードを使わず、少し抽象化して いる • JOOQとKtormは近いが、JOOQの方がonをチェーンし て書いてる分、より生のSQLに近い印象
サブクエリ
select * from USERS where exists( select * from USER_PURCHASE_HISTORIES
where USERS.id = USER_PURCHASE_HISTORIES.user_id );
Users.select(Users.columns) .where { exists( UserPurchaseHistories .select(UserPurchaseHistories.id).where{ Users.id eq UserPurchaseHistories.userId }
) } Exposed
dslContext.selectFrom(USERS) .whereExists( dslContext.selectOne() .from(USER_PURCHASE_HISTORIES) .where(USER_PURCHASE_HISTORIES.USER_ID.eq(USERS.ID)) ) .fetch() JOOQ
database .from(Users) .select() .where { exists( database.from(UserPurchaseHistories) .select(UserPurchaseHistories.id) .where {
UserPurchaseHistories.userId eq Users.id } ) } Ktorm
• JOOQだけwhereExists、selectOneなどの関数があり 少し抽象化されている • ExposedとKtormはwhere→exists→selectの階層に なっており、生のSQLに近い
JOINして絞り込む
select USERS.id, USERS.name, sum(USER_PURCHASE_HISTORIES.price) from USERS left join USER_PURCHASE_HISTORIES on
USERS.id = USER_PURCHASE_HISTORIES.user_id where USERS.age >= 20 group by USERS.id having sum(USER_PURCHASE_HISTORIES.price) >= 3000;
Users.leftJoin(UserPurchaseHistories , { Users.id }, { UserPurchaseHistories .userId }) .select(Users.id,
Users.name, UserPurchaseHistories .price.sum()) .where { Users.age greaterEq 20 } .groupBy(Users.id) .having { UserPurchaseHistories .price.sum() greaterEq 3000 } Exposed
dslContext.select(USERS.ID, USERS.NAME, DSL.sum(USER_PURCHASE_HISTORIES.PRICE)) .from(USERS) .leftJoin(USER_PURCHASE_HISTORIES) .on(USERS.ID.eq(USER_PURCHASE_HISTORIES.USER_ID)) .where(USERS.AGE.ge(20)) .groupBy(USERS.ID) .having(DSL.sum(USER_PURCHASE_HISTORIES.PRICE). ge(BigDecimal(3000)))
.fetch() JOOQ
database .from(Users) .leftJoin(UserPurchaseHistories, on = Users.id eq UserPurchaseHistories .userId) .select(Users.id,
Users.name, sum(UserPurchaseHistories.price)) .where { Users.age greaterEq 20 } .groupBy(Users.id, Users.name) .having { sum(UserPurchaseHistories.price) greaterEq 3000 } Ktorm
• 少し複雑で長いSQLになった分、構文で抽象化してい るExposedの短さがより際立っている • JOOQは生のSQLに近い構文な上、”DSL.”のように書か なければいけないキーワードが多いので長い
アジェンダ 1. Kotlin Fest 2024の振り返り 2. 各種O/Rマッパーのおさらい 3. 色々なSQLを実装してみる 4.
まとめ
4. まとめ
• 書きたいわけではないが、書く以外でいいソリュー ションがない • SQLだけ抽象化された状態では微妙 • 結果SQLっぽく書けるO/Rマッパーが好まれやすい エンジニアはSQLを書きたい?
• ExposedはFROMを省略したりJOINの書き方が簡略化 されたりと、少し短く書けるようになっている • JOOQは一番SQLに近い構文で書ける印象 • KtormもSQLに近いが、句の順序やJOINの書き方など 一部差分がある 各種O/Rマッパーの特性
Have a nice Server-side Kotlin!