spring-data-jpa について
Spring Data JPA プロジェクト向けのデータアクセスパターンを扱うスキルです。リポジトリ、エンティティ関係、クエリ、ページネーション、監査、トランザクションをカバーし、永続化層の構築や最適化に使えます。
主な機能
- 01リポジトリインターフェースと派生クエリ
- 02エンティティ関係とカスケード設定
- 03カスタムクエリとページネーション
- 04監査フィールドとトランザクション管理
- 05クエリ性能と N+1 問題の最適化
活用シーン
- 01CRUD リポジトリとカスタムクエリの作成
- 02エンティティ関係とカスケードの設定
- 03大規模データセットへのページネーション追加
- 04クエリ性能や N+1 問題の調査
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ giuseppe-trisciuoglio/ developer-kit --skill spring-data-jpaインストール後、Claude Code で/spring-data-jpaを入力して読み込まれたか確認します。
同梱ファイルreferences/examples.mdreferences/reference.md
詳細
Spring Data JPA
概要
Spring Data JPA リポジトリ、エンティティのリレーションシップ、クエリ、ページネーション、監査、トランザクションのパターンを提供します。
使用する場面
CRUD 操作を備えたリポジトリ、エンティティのリレーションシップ、@Query アノテーション、ページネーション、監査、または UUID 主キーを作成する場合に使用します。
手順
リポジトリインターフェースを作成する
リポジトリインターフェースを実装するには、次の手順に従います。
-
適切なリポジトリインターフェースを継承します。
@Repository public interface UserRepository extends JpaRepository<User, Long> { // Custom methods defined here } -
シンプルな条件には派生クエリを使用します。
Optional<User> findByEmail(String email); List<User> findByStatusOrderByCreatedDateDesc(String status); -
@Query を使ってカスタムクエリを実装します。@Query("SELECT u FROM User u WHERE u.status = :status") List<User> findActiveUsers(@Param("status") String status);
エンティティを設定する
-
適切なアノテーションを使ってエンティティを定義します。
@Entity @Table(name = "users") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(nullable = false, length = 100) private String email; } -
適切なカスケードタイプを使ってリレーションシップを設定します。
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true) private List<Order> orders = new ArrayList<>();検証: 本番データに適用する前に、小規模なデータセットでカスケードの動作をテストします。削除操作で意図しないカスケードが発生しないことを確認します。
-
データベース監査を設定します。
@CreatedDate @Column(nullable = false, updatable = false) private LocalDateTime createdDate;
クエリのパターンを適用する
- シンプルな条件には派生クエリを使用します
- 複雑なクエリには
@Query を使用します - 単一の結果には Optional を返します
- ページネーションには Pageable を使用します
- 更新/削除操作には
@Modifying を適用します
トランザクションを管理する
- 読み取り専用の操作には
@Transactional(readOnly = true) を指定します - 変更操作には明示的なトランザクション境界を使用します
- 必要に応じてロールバック条件を指定します
検証と最適化
1. エンティティの設定を検証します。
- 本番環境へのデプロイ前に、トランザクション内でカスケードの動作をテストします
- 双方向リレーションシップが正しく同期されることを検証します
2. クエリのパフォーマンスを最適化します。
- 大きなテーブルに対するクエリで
EXPLAIN ANALYZEを実行します - パフォーマンスの問題が検出された場合:インデックスを追加 → EXPLAIN で確認 → 繰り返します
@EntityGraphを使用して N+1 クエリを防ぎます
3. ページネーションを検証します。
- インデックス付きのカラムがページネーションクエリをサポートしていることを確認します
- カーソルの安定性を検証するため、大規模なデータセットでテストします
例
基本的な CRUD リポジトリ
@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {
// Derived query
List<Product> findByCategory(String category);
// Custom query
@Query("SELECT p FROM Product p WHERE p.price > :minPrice")
List<Product> findExpensiveProducts(@Param("minPrice") BigDecimal minPrice);
}
ページネーションの実装
@Service
public class ProductService {
private final ProductRepository repository;
public Page<Product> getProducts(int page, int size) {
Pageable pageable = PageRequest.of(page, size, Sort.by("name").ascending());
return repository.findAll(pageable);
}
}
監査機能付きエンティティ
@Entity
@EntityListeners(AuditingEntityListener.class)
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@CreatedDate
@Column(nullable = false, updatable = false)
private LocalDateTime createdDate;
@LastModifiedDate
private LocalDateTime lastModifiedDate;
@CreatedBy
@Column(nullable = false, updatable = false)
private String createdBy;
}
ベストプラクティス
エンティティ設計
- コンストラクターインジェクションのみを使用します(フィールドインジェクションは使用しません)
final修飾子を使った不変フィールドを優先します- DTO には Java のレコード(16 以降)または
@Valueを使用します - 適切な
@Idおよび@GeneratedValueアノテーションを必ず指定します - 明示的な
@Tableおよび@Columnアノテーションを使用します
パフォーマンスの最適化
- 適切なフェッチ戦略(LAZY と EAGER)を使用します
- 大規模なデータセットにはページネーションを実装します
- 頻繁にクエリされるフィールドにはデータベースインデックスを使用します
- N+1 クエリの問題を避けるために
@EntityGraphの使用を検討します
リファレンスドキュメント
包括的な例、詳細なパターン、高度な設定については、以下を参照してください。
制約と警告
- JPA エンティティを REST API で直接公開しないでください。遅延ロードの問題を防ぐため、必ず DTO を使用します。
@EntityGraphまたはクエリ内のJOIN FETCHを使用して、N+1 クエリの問題を回避します。- 大規模なコレクションでの
CascadeType.REMOVEは、パフォーマンスの問題を引き起こす可能性があるため注意してください。 - コレクションに
EAGERフェッチタイプを使用しないでください。データベースクエリが過剰に発生する可能性があります。 - データベースのロック競合を引き起こす可能性があるため、長時間実行されるトランザクションは避けてください。
- 最適化を有効にするため、読み取り操作には
@Transactional(readOnly = true)を使用します。 - 第 1 レベルキャッシュに注意してください。同一トランザクション内では、エンティティにデータベースの変更が反映されない場合があります。
- UUID 主キーはインデックスの断片化を引き起こす可能性があるため、シーケンシャル UUID または Long ID の使用を検討します。
- 大規模なデータセットのページネーションでは、テーブル全体のスキャンを避けるため、適切なインデックスが必要です。
コメント
Markdown 対応