Spring Data JPA 実践 — Repository · N+1 · DTO 変換
Spring Data JPA 実践 — Repository · N+1 · DTO 変換
🎯 このレッスンを読み終えたら
このレッスンをすべて読み終えると、以下の3つを自信を持ってできるようになります。
- ▸✅ JpaRepository を継承するだけで 0行のコード で CRUD を実装
- ▸✅ N+1 問題 → @EntityGraph または JOIN FETCH で解決
- ▸✅ Lazy vs Eager の違い + 実務では必ず Lazy を使う理由
学習目標を チェックリストとして 手元に置き、すべてに答えられるようになったらレッスンを閉じてください。
JpaRepository — *メソッド名を付けるだけで完成*
最大の魔法
インターフェース1行 を宣言するだけで — Spring が 実行時に実装クラスを自動生成 します。すぐ使えるメソッド:
- ▸
save(entity)— INSERT または UPDATE - ▸
findById(id)— Optional を返す - ▸
findAll()— 全件取得 - ▸
count()— 件数取得 - ▸
deleteById(id)— 削除 - ▸
existsById(id)— 存在確認
メソッド名でクエリを生成する
メソッド名の命名規則 に従うだけで、Spring が 自動的に SQL を生成。可読性とパフォーマンスの両方で圧勝です。
キーワード: findBy、countBy、existsBy、deleteBy + フィールド名 + (Containing、GreaterThan、In、Between、OrderBy...Asc/Desc ...)
JPQL を直接書く — @Query
複雑なクエリは JPQL (Java Persistence Query Language) で記述します:
JPQL は SQL に似ていますが、「エンティティ名」で記述します — テーブル名ではありません。
ページング — Pageable
無限スクロール も ページナビゲーション も、これ一つで完結します。
N+1 問題 — 実務で最もよく遭遇する落とし穴
問題の状況
ユーザーが100人 → クエリが101回 発生。データが増えるほど 指数的に遅くなります。これが N+1 問題 です。
解決策1 — @EntityGraph(最もシンプル)
1回の JOIN クエリで完結。SQL にすると:
解決策2 — JOIN FETCH(JPQL 直接記述)
DISTINCT が重要 — 付けないと 重複行 が増えます。
解決策3 — Batch Size (@BatchSize)
完全な解決ではありませんが、N+1 を N/バッチサイズ+1 に削減。複数の関連 + ページングの組み合わせで有効です。
Lazy vs Eager — いつどちらを使うか
実務ルール: 必ず LAZY。EAGER は 予測不可能なクエリ爆発 の原因になります。必要なときは都度 @EntityGraph または JOIN FETCH を使いましょう。
N+1 のデバッグ — show-sql をオンにする
開発中 はコンソールに実際に発行された SQL が表示されます。同じクエリが 何十回も繰り返される 場合は N+1 の疑いがあります。
Entity → DTO 変換 — *なぜ分離すべきか*
Entity をそのまま返してはいけない理由
4つの問題:
1. 循環参照: User ↔ Order の双方向マッピングがあると JSON の無限シリアライズ → StackOverflow。
2. 機密情報の露出: password や internalNote などのフィールドが 自動的に公開される。
3. API スキーマと DB スキーマの結合: DB のカラム名を変えると API も壊れる。
4. 不要なクエリ: Jackson が Lazy フィールドをシリアライズしようとして 追加クエリが発生する。
DTO パターン
スタティックファクトリメソッド (from) が変換の責務を持ち、Entity と DTO が 互いを知らない関係 を保ちます。
入力用 DTO も分離する
@Valid が Bean Validation (@Email・@NotBlank・@Size) を自動実行。バリデーション失敗時は 400 Bad Request が自動返却されます。
MapStruct — 変換コードを自動生成する
DTO が増えると from() メソッドも増えていきます。MapStruct ライブラリは コンパイル時に変換コードを生成 し、ボイラープレートを排除します。
中・大規模プロジェクトの標準手法 です。最初は手で書き、慣れてきたら導入しましょう。
🤖 AI にこう依頼してみましょう
このレッスンの概念を理解すれば、AI に 具体的に 指示できるようになります。漠然とした「直して」ではなく、語彙を持ったリクエスト — それがトークン節約の出発点です。
- ▸「この findAll + ループが N+1 になっているので @EntityGraph で解決して」
- ▸「この Entity を UserResponse DTO に変換する static factory メソッドを追加して」
- ▸「JpaRepository に findByEmailAndActive メソッドのシグネチャを追加して」
なぜこれがトークンを削減するのか
概念を知らないままだと、AI の回答を受け取っても 「それって何ですか?」 とまた聞き直すことになります。その「聞き直し」がトークンを消費します。概念を一度しっかり理解しておけば、会話が一度で完結 します。