🔍 Spring Framework 講座【第21回】DB検索を自動化!〜Spring Data JPAのCRUDとカスタム検索〜

docs

前回、JPAの基本概念と、Spring Data JPAによってインターフェースとしてRepositoryを定義するだけで、基本的なDB操作メソッド(savefindByIdなど)が自動生成されることを学びました。

この機能のおかげで、私たちはデータを「作成 (Create)」「読み取り (Read)」「更新 (Update)」「削除 (Delete)」するCRUD操作のほとんどで、SQL文を書く必要がなくなりました。

今回は、この自動生成されたCRUDメソッドの使い方と、さらに一歩進んで、独自の検索条件(例: 名前で検索、価格で検索)を追加する方法を学びます。

1. Spring Data JPAによる基本的なCRUD操作

Spring Data JPAの核となる JpaRepository<Entity, 主キー型> インターフェースには、すでに以下のような基本的なCRUDメソッドが定義されています。

メソッド名概要対応するSQL操作
save(entity)Entityの保存または更新INSERT / UPDATE
findById(id)主キー(ID)によるEntityの検索SELECT
findAll()全てのEntityの検索SELECT
delete(entity)Entityの削除DELETE
count()Entityの総数をカウントSELECT COUNT

これらのメソッドは、Service層から ItemRepository のBeanをDIで受け取り、呼び出すだけで利用できます。

【Service層での利用例】

Java

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class ItemService {
    
    private final ItemRepository itemRepository;
    
    // 1. 作成・更新 (Create / Update)
    public Item save(Item item) {
        // save()は、IDがセットされていなければ新規作成、セットされていれば更新を行う
        return itemRepository.save(item);
    }
    
    // 2. 読み取り (Read)
    public Item findItem(Long itemId) {
        // findById()は Optional<Item> を返すため、orElseThrow()などで処理する
        return itemRepository.findById(itemId)
                             .orElseThrow(() -> new RuntimeException("商品が見つかりません: " + itemId));
    }
    
    // 3. 削除 (Delete)
    public void delete(Item item) {
        itemRepository.delete(item);
    }
}

2. カスタム検索:メソッド名によるクエリ生成

Spring Data JPAの最も強力な機能は、「特定のルールに従ったメソッド名」をRepositoryインターフェースに記述するだけで、Springが自動的にSQLを生成し、検索処理を実装してくれることです。これをクエリ生成機能と呼びます。

2-1. メソッド命名規則

検索メソッド名は、findBy から始まり、その後に検索したいEntityのフィールド名を結合子(AndOrなど)で繋いで記述します。

メソッド名意味
findBy{フィールド名}(引数)指定したフィールドの値に一致するレコードを検索
findBy{フィールド名}And{フィールド名2}(引数1, 引数2)複数の条件に全て一致するレコードを検索
findBy{フィールド名}OrderBy{フィールド名2}Desc()フィールド2で降順に並び替えて検索

【ItemRepository へのカスタム検索の追加】

Item Entityに name(String)と price(int)フィールドがあると仮定します。

Java

import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;

public interface ItemRepository extends JpaRepository<Item, Long> {
    
    // 1. 名前で検索
    // WHERE name = ?
    List<Item> findByName(String name); 
    
    // 2. 名前の部分一致検索(キーワードを含む)
    // WHERE name LIKE %?%
    List<Item> findByNameContaining(String keyword); 
    
    // 3. 価格帯で検索
    // WHERE price BETWEEN ? AND ?
    List<Item> findByPriceBetween(int minPrice, int maxPrice); 
    
    // 4. 複合条件と並び替え
    // WHERE name = ? AND price < ? ORDER BY price DESC
    List<Item> findByNameAndPriceLessThanOrderByPriceDesc(String name, int maxPrice);
}

このように、SQL文を一切書かずに、Javaのメソッド名だけで複雑な検索条件を表現できます。Spring Data JPAが、実行時にこのメソッド名に対応する適切なSQLを組み立ててくれます。


3. メソッドの戻り値の型

クエリ生成メソッドの戻り値の型は、検索結果の件数や目的に応じて使い分けます。

戻り値の型意味
List<Entity>複数件の結果(最も一般的)
Entity検索結果が必ず1件であることを想定
Optional<Entity>検索結果が0件または1件であることを想定(安全性が高い)
void更新・削除などの実行(戻り値がない場合)

例えば、IDではないがユニークなフィールド(例: ユーザーのメールアドレス)で検索する場合、結果が1件か0件なので Optional<User> を使うのが安全です。

Java

// メールアドレスは重複しない想定
Optional<User> findByEmail(String email); 

4. まとめ:生産性を高めるSpring Data JPA

Spring Data JPAのクエリ生成機能は、定型的なDB検索を驚くほど簡単にします。開発者は、SQLの知識よりも**「どのような検索をしたいか」**をJavaのメソッド名として表現することに集中できます。

しかし、メソッド名では表現できないほど複雑な検索や、DB固有の高度なSQL機能を使いたい場合もあります。

✅ 本日のまとめ

  • Spring Data JPAの JpaRepository が提供するメソッドで、CRUD操作のほとんどが実現できる。
  • クエリ生成機能findBy から始まる特定の命名規則に従ったメソッド名を定義するだけで、Springが自動でSQLを生成する。
  • AndOrBetweenContaining などの結合子をメソッド名に含めることで、複雑な検索条件を設定できる。
  • 戻り値の型は、検索結果の件数(ListOptionalEntity)によって使い分ける。

🔔 次回予告

メソッド名によるクエリ生成は便利ですが、あまりに複雑な検索になるとメソッド名が長くなりすぎたり、表現できなかったりします。

次回は、より複雑でDB固有のSQLを使いたい場合に、自分でSQL文を直接書いて検索メソッドを実装する方法(@Query アノテーションの利用)を学びます。

次回:【第22回】Spring Data JPA (2) – @QueryによるカスタムSQLとJPQL にご期待ください!

コメント

タイトルとURLをコピーしました