カテゴリ: Spring 更新日: 2026/04/05

SpringのPageableとSortでページング一覧APIを最短実装!初心者向け完全ガイド

ページングとソート(Pageable/Sort)を最短実装:一覧APIの定石
ページングとソート(Pageable/Sort)を最短実装:一覧APIの定石

先生と生徒の会話形式で理解しよう

生徒

「Spring Bootで一覧APIを作るときに、データをページ分けしたいんですけど、どうすればいいですか?」

先生

「SpringにはPageableSortという便利な機能があって、それを使えば簡単にページング処理やソートが実装できますよ。」

生徒

「えっ、それってController側に全部書くんですか?」

先生

「いい質問ですね。実はSpring Data JPAと組み合わせると、リポジトリレイヤーでも簡潔に書けるんです。さっそく一緒に実装してみましょう!」

1. Pageableとは?ページング処理の基本

「1. Pageableとは?ページング処理の基本」の重要ポイントを、初心者の方にも分かりやすく簡潔に解説します。

1. Pageableとは?ページング処理の基本
1. Pageableとは?ページング処理の基本

Spring FrameworkやSpring Bootで大量のデータを扱う際、データベースにある全レコードを一度に取得して画面に表示しようとすると、読み込みに時間がかかりすぎてしまいます。例えば、数万件のデータがある通販サイトで、全商品を1ページに表示しようとしたら、ブラウザが固まってしまいますよね。

これを解決するのがページング(Pagination)という技術です。本をページごとにめくるように、データを「1ページ10件ずつ」といった単位で分割して取得します。Springでは、このページ分割のルールを管理するためにPageableというインターフェースが用意されています。

プログラミング未経験者向けのイメージ例

例えば、100個のリンゴがあるとき、一度に全部運ぶのは大変です。そこで、「1回に10個ずつ運ぶ(サイズ)」と決めて、「今は何回目の運搬か(ページ番号)」を指定して運ぶのが、Pageableの役割です。

具体的には、URLの末尾にクエリパラメータを付けるだけで、Springが自動的に「何件目から何件取得するか」を計算してくれます。


http://localhost:8080/api/books?page=0&size=5

このように、page(ページ番号 ※0から開始)size(1ページあたりの件数)sort(並び替え条件)という3つの要素を組み合わせることで、ユーザーにとって見やすく、サーバーに負担をかけない高速なAPIを簡単に構築できるのがPageableの最大のメリットです。

2. Spring Data JPAでPageableを使う方法

2. Spring Data JPAでPageableを使う方法
2. Spring Data JPAでPageableを使う方法

Spring Data JPAの最大の魅力は、複雑なSQLクエリを書かなくても、メソッドの引数にPageableを追加するだけでページング処理が完成する点にあります。通常、SQLでページングを行うには「LIMIT」や「OFFSET」を手動で計算して記述する必要がありますが、Spring Data JPAがその計算をすべて代行してくれます。

初心者向けのポイント

リポジトリのメソッドの戻り値をList<T>ではなくPage<T>にすることで、データ本体だけでなく「全部で何ページあるか」といった便利な情報も一緒に受け取れるようになります。

まずは、データベースを操作するRepository(リポジトリ)の設定です。JpaRepositoryを継承していれば、標準的なfindAll(Pageable pageable)は既に利用可能な状態になっています。


public interface BookRepository extends JpaRepository<Book, Long> {
    // Pageableを引数に渡すと、自動的にページング用SQLが発行される
    Page<Book> findAll(Pageable pageable);
}

次に、外部からのリクエストを受け取るController(コントローラー)を実装します。ここで注目すべきは、Pageableを引数に書くだけで、Springがブラウザからのパラメータ(pageやsize)を自動で解析してオブジェクト化してくれる仕組みです。


@RestController
@RequestMapping("/books")
public class BookController {

    private final BookRepository bookRepository;

    public BookController(BookRepository bookRepository) {
        this.bookRepository = bookRepository;
    }

    @GetMapping
    public Page<Book> getBooks(Pageable pageable) {
        // 受け取ったpageableをそのままリポジトリに渡すだけ!
        return bookRepository.findAll(pageable);
    }
}

この実装だけで、例えば /books?page=0&size=5 というURLにアクセスすると、データベースの1件目から5件目までをスマートに取得できます。もしパラメータを何も指定しなかった場合は、Spring Bootの標準設定(通常は1ページ20件など)が適用されるため、エラーになる心配もありません。

このように、開発者は「どのデータを何件取得するか」というビジネスロジックに集中でき、面倒な計算処理はフレームワークに任せることができるのです。

3. Sortを使った並び順の変更

3. Sortを使った並び順の変更
3. Sortを使った並び順の変更

並び順(ソート)も、Sortを通じてPageableに組み込むことができます。ユーザー一覧をname昇順で表示したい場合、?sort=name,ascとするだけです。

複数条件のソートも可能で、?sort=name,asc&sort=id,descと指定することで、まず名前の昇順、その次にIDの降順になります。

リクエストURL例:


/books?page=1&size=10&sort=publishedDate,desc

4. デフォルト値の指定やバリデーションを加える方法

「4. デフォルト値の指定やバリデーションを加える方法」の重要ポイントを、初心者の方にも分かりやすく簡潔に解説します。

4. デフォルト値の指定やバリデーションを加える方法
4. デフォルト値の指定やバリデーションを加える方法

Pageableの初期値を指定したい場合は、@PageableDefaultアノテーションを使うことで、デフォルトのページサイズやソート条件を設定できます。


@GetMapping("/books/default")
public Page<Book> getBooksDefault(
        @PageableDefault(size = 5, sort = "title", direction = Sort.Direction.ASC)
        Pageable pageable) {
    return bookRepository.findAll(pageable);
}

このようにしておくと、クエリパラメータが指定されなかった場合でも、安定したレスポンスが返せます。

5. ページングレスポンスの中身を理解しよう

5. ページングレスポンスの中身を理解しよう
5. ページングレスポンスの中身を理解しよう

Page<T>型の戻り値には、対象のデータだけでなく、ページ全体に関するメタ情報も含まれています。

  • content:現在のページのデータリスト
  • totalElements:全件数
  • totalPages:総ページ数
  • number:現在のページ番号
  • size:ページサイズ
  • first / last:先頭ページか末尾ページかの判定

この情報を使えば、「次へ」「前へ」などのページネーションリンクも実装しやすくなります。

6. REST APIでページングとソートを活用する実例

6. REST APIでページングとソートを活用する実例
6. REST APIでページングとソートを活用する実例

実務では、検索や一覧画面において、ページングとソートを同時に扱うことが一般的です。

Spring BootでREST APIを作成する際は、以下のようなリクエストURLが実際に使われます。


/books?page=2&size=20&sort=author,desc

APIの戻り値はJSON形式で、フロントエンドに渡しやすく、AngularやReact、Vue.jsなどとも相性抜群です。

7. ページングとソートをカスタムクラスに変換する

「7. ページングとソートをカスタムクラスに変換する」の重要ポイントを、初心者の方にも分かりやすく簡潔に解説します。

7. ページングとソートをカスタムクラスに変換する
7. ページングとソートをカスタムクラスに変換する

Page<T>はそのままだと使いにくい場合もあるため、レスポンスを独自DTO(Data Transfer Object)に変換するのもおすすめです。

例えば、以下のようなレスポンス構造に変換できます:


public class BookPageResponse {
    private List<BookDto> content;
    private int currentPage;
    private int totalPages;
    private long totalElements;
    // getter/setter 略
}

8. PageableとSortを使うときの注意点

8. PageableとSortを使うときの注意点
8. PageableとSortを使うときの注意点

最後に、ページングとソートを使う際のよくある落とし穴を整理しておきます。

  • ソート対象のフィールド名が間違っていると実行時エラーになる
  • デフォルトページサイズが大きすぎるとレスポンスが重くなる
  • ソート条件がユーザー入力のままだとSQLインジェクションの可能性も

こうしたリスクを避けるには、制限を設ける・ログ出力を強化する・明示的なバリデーションを加えることが推奨されます。

まとめ

まとめ
まとめ

本記事では、Spring Bootにおいて非常に強力なツールであるPageableSortを用いた、ページング一覧APIの実装方法について詳しく解説してきました。WebアプリケーションやモダンなSPA(Single Page Application)を構築する際、大量のデータを一度に取得してクライアントに返却することは、サーバー負荷の増大やネットワーク帯域の圧迫、そしてユーザー体験(UX)の低下を招く大きな要因となります。そのため、実務レベルの開発において、適切なページング処理とソート機能の実装は避けて通れない必須スキルと言えるでしょう。

ページング実装の重要性とSEO効果

検索エンジン最適化(SEO)の観点からも、ページングは非常に重要です。大量のコンテンツを適切に分割し、関連性の高いデータを上位に表示させることは、クローラーの巡回効率を高め、ユーザーが必要な情報に素早くアクセスできる環境を提供することに直結します。JavaのSpring Frameworkが提供するPageableインターフェースを利用することで、開発者は複雑なSQLのLIMIT句やOFFSET句を直接記述することなく、オブジェクト指向的なアプローチでこれらの機能を統合できます。

サンプルプログラム:より実践的なサービス層での活用

これまでの章ではリポジトリとコントローラーの連携を見てきましたが、ここでは実際のビジネスロジックを想定し、サービス層(Service Layer)を介したより堅牢な実装サンプルを紹介します。DTO(Data Transfer Object)への変換処理も含めることで、APIの外部仕様とデータベースのエンティティ構造を分離し、保守性の高いコードを実現します。


@Service
@Transactional(readOnly = true)
public class BookService {

    private final BookRepository bookRepository;

    public BookService(BookRepository bookRepository) {
        this.bookRepository = bookRepository;
    }

    /**
     * 書籍一覧をページング形式で取得し、DTOに変換して返却します。
     * @param pageable ページング情報
     * @return 変換済みのページオブジェクト
     */
    public Page<BookResponseDto> findAllBooks(Pageable pageable) {
        // RepositoryからエンティティのPageを取得
        Page<Book> bookPage = bookRepository.findAll(pageable);
        
        // エンティティからDTOへ変換(mapメソッドを活用)
        return bookPage.map(book -> new BookResponseDto(
                book.getId(),
                book.getTitle(),
                book.getAuthor(),
                book.getPublishedDate()
        ));
    }
}

このように、Page.map()メソッドを使用することで、ページングのメタ情報を維持したまま、中身のコンテンツだけをスマートに変換することが可能です。これは、APIレスポンスのセキュリティを確保し、必要なフィールドのみを公開する際に非常に有効な手法です。

PageableとSortを使いこなすためのヒント

さらに高度な活用方法として、複数のソート条件をプログラム内で動的に生成することも可能です。例えば、特定の条件下では「作成日」の降順、それ以外では「タイトル」の昇順といった制御が必要な場合、以下のようにSortオブジェクトを個別に定義できます。


// 動的なソート条件の生成例
Sort sort = Sort.by("publishedDate").descending()
                .and(Sort.by("title").ascending());
Pageable customPageable = PageRequest.of(pageNumber, pageSize, sort);

これにより、URLパラメータに依存しない、システム内部での厳密な並び順制御が可能になります。Spring Bootの強力なエコシステムを理解し、これらの機能を適切に組み合わせることで、スケーラビリティに優れたバックエンドAPIを短期間で構築できるようになるでしょう。

先生と生徒の振り返り会話

生徒

「先生、ありがとうございました!Pageableを使うだけで、あんなに面倒だったページングの計算やSQL発行が自動化されるなんて驚きです。今までわざわざ件数をカウントするクエリを別で書いていたのが嘘みたいです。」

先生

「そうですね。Page<T>を戻り値にするだけで、全件数(totalElements)や総ページ数(totalPages)まで取得してくれるのは、Spring Data JPAの大きなメリットの一つです。フロントエンドのページネーション部品を作る時にも、その情報がそのまま使えるので非常に効率的ですよ。」

生徒

「はい、JSONレスポンスの中にlast: trueとかfirst: trueというフラグが入っているのを見て、これなら『次のページへ』ボタンの活性・非活性の制御も簡単にできるなと思いました。ソートについても、URLに?sort=price,descと付けるだけでいいのは直感的ですね。」

先生

「その通りです。ただ、記事の最後でも触れたように、ソート対象のフィールド名はJavaのエンティティのプロパティ名と一致させる必要があります。もし間違えると、PropertyReferenceExceptionというエラーが発生してアプリが止まってしまうので、そこだけは注意しましょうね。」

生徒

「プロパティ名ですね、気をつけます!あと、デフォルト値を設定する@PageableDefaultも便利そうでした。これを設定しておけば、もしユーザーがパラメータを何も指定しなくても、システムがパンクするような大量データ取得を防げますもんね。」

先生

「素晴らしい洞察です。パフォーマンスとセキュリティの両面を意識するのはエンジニアとして大切です。さらにステップアップするなら、QuerydslSpecificationと組み合わせて、複雑な検索条件とページングを両立させる方法も学んでみると面白いですよ。」

生徒

「検索条件との組み合わせ……難しそうですが、やりがいはありそうです。まずは今回のPageableSortを自分のプロジェクトに組み込んで、使い倒してみます!」

先生

「その意気です!もし実装途中で詰まったら、いつでも聞いてくださいね。Spring Bootの機能をフル活用して、スマートなAPIを完成させましょう!」

カテゴリの一覧へ
新着記事
New1
Spring
Spring Securityの新標準!SecurityFilterChainとHttpSecurity DSLの書き方を初心者向けに解説
更新記事
New2
Java
Javaの抽象クラス(abstract)を完全ガイド!継承と設計のルールを学ぶ
更新記事
New3
Servlet
JavaのGenericServletクラスのgetInitParameterNamesメソッドを徹底解説!初心者でもわかる初期化パラメータの取得方法
更新記事
New4
JSP
JSPとは何か?初心者向けにできること・仕組み・特徴をやさしく解説
更新記事
人気記事
No.1
Java&Spring記事人気No1
Spring
Spring BootとJavaの互換性一覧!3.5/3.4/3.3はJava 21・17に対応してる?
No.2
Java&Spring記事人気No2
Servlet
JavaのHttpSessionを徹底解説!初心者でもわかるセッション管理の基本
No.3
Java&Spring記事人気No3
Java
JavaのIOExceptionクラス徹底解説!初心者向けファイル入出力エラー対策ガイド
No.4
Java&Spring記事人気No4
Spring
Springの@Serviceアノテーションの使い方を徹底解説!初心者でもわかるSpring フレームワーク入門
No.5
Java&Spring記事人気No5
JSP
JSPの基本タグ一覧と使い方まとめ!実務で使えるタグを紹介
No.6
Java&Spring記事人気No6
Java
Java開発環境「Eclipse(Pleiades)」のインストール方法とメリットを初心者向けに解説
No.7
Java&Spring記事人気No7
Spring
Spring BootとVS Codeで開発を始めよう!拡張機能・launch.json・ホットリロードを丁寧に解説
No.8
Java&Spring記事人気No8
Spring
Springの@Componentアノテーションの使い方を徹底解説!初心者でもわかるSpring Boot入門