Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
「2024年版 Kotlin サーバーサイドプログラミング実践開発」の補講 〜O/Rマッパー編〜
Search
Takehata Naoto
July 18, 2024
Programming
850
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
「2024年版 Kotlin サーバーサイドプログラミング実践開発」の補講 〜O/Rマッパー編〜
2024年7月18日(土) 「Server-side Kotlin Night 2024/07」の発表資料です。
Takehata Naoto
July 18, 2024
More Decks by Takehata Naoto
See All by Takehata Naoto
AI時代でも変わらない技術コミュニティの力~10年続く“ゆるい”つながりが生み出す価値
n_takehata
2
1.4k
KotlinConf 2025で発表された言語のアップデートと現地参加レポート
n_takehata
2
410
KotlinConf 2025 現地で感じたServer-Side Kotlin
n_takehata
2
520
KotlinConf 2025 現地参加の土産話
n_takehata
0
230
組織貢献をするフリーランスエンジニアという生き方
n_takehata
1
6.8k
2024年版 Kotlin サーバーサイドプログラミング実践開発
n_takehata
9
9.2k
Server-Side目線で見る、Kotlin Festの楽しみ方
n_takehata
0
670
KotlinとCloud Vision APIで領収書の電子帳簿保存法対応をする
n_takehata
1
2.1k
KotlinConf 2023 現地参加レポート
n_takehata
1
430
Other Decks in Programming
See All in Programming
UPDATE をやめる — EF Core でマスタをバージョン管理する
panda728
PRO
0
320
Webの地図
yosuke_furukawa
PRO
6
4.7k
setup-vp GitLab対応の裏側
naokihaba
0
120
XHTMLが残したもの
yosuke_furukawa
PRO
2
830
Security issues being discussed on Web Platforms
petamoriken
0
1k
変化を抱擁するドキュメントの作り方 - ビジネスルール駆動開発がもたらす、コードとの新しい関係
ioki
2
220
Heart of Swift Concurrency
koher
0
950
AWS Step Functions 大規模並列の壁を越える / jaws-sonic-2026-niigata-step-functions
kasacchiful
PRO
1
500
JPUG勉強会 OSSデータベースの内部構造を理解しよう(第2回)
oga5
0
270
モバイル交通系ICへのチャージ実例から考える、クロスプラットフォーム開発におけるiOS実機テスト設計とCI運用
yusuga
1
530
MVNOの申込からeSIM開通までをiOSアプリでつなぐ- 本人確認・MNP・通信事業者基盤をまたぐ実装
satotakeshi
0
450
AI が書く Go コードの品質を劇的に向上させる Linter: “declscope”
mpyw
0
380
Featured
See All Featured
Hiding What from Whom? A Critical Review of the History of Programming languages for Music
tomoyanonymous
3
1.2k
Collaborative Software Design: How to facilitate domain modelling decisions
baasie
1
320
Making the Leap to Tech Lead
cromwellryan
135
10k
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
1
830
DevOps and Value Stream Thinking: Enabling flow, efficiency and business value
helenjbeal
1
390
Imperfection Machines: The Place of Print at Facebook
scottboms
270
14k
Producing Creativity
orderedlist
PRO
348
41k
Design of three-dimensional binary manipulators for pick-and-place task avoiding obstacles (IECON2024)
konakalab
0
600
The Limits of Empathy - UXLibs8
cassininazir
1
680
Balancing Empowerment & Direction
lara
6
1.3k
Unlocking the hidden potential of vector embeddings in international SEO
frankvandijk
0
940
Ethics towards AI in product and experience design
skipperchong
2
380
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!