カテゴリ: Spring 更新日: 2026/07/10

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を使った並び順の変更

ページングとセットで欠かせないのがソート(並び替え)機能です。SpringではSortクラスを利用することで、データベースから取得するデータの順番を自由自在にコントロールできます。

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

クローゼットの中にある服を想像してください。「購入したのが新しい順」に並べたり、「色の名前順」に並べたりしますよね。Sortは、まさにその「並び替えのルール」を指定する役割を持っています。

使い方は非常にシンプルです。URLのパラメータにsort=フィールド名,方向を付け加えるだけで、Spring Data JPAが自動的にSQLのORDER BY句を生成してくれます。方向には、昇順(小さい順)のascと、降順(大きい順)のdescが指定可能です。

例えば、本のリストを「出版日が新しい順(降順)」で取得したい場合は、以下のようなリクエストになります。


http://localhost:8080/books?page=0&size=10&sort=publishedDate,desc

また、複数の条件を組み合わせることも可能です。例えば「著者名で並び替えて、同じ著者の場合はID順にする」といった複雑な指定も、パラメータを繋げるだけで実現できます。


http://localhost:8080/books?sort=author,asc&sort=id,desc

このようにPageableの中にSortの情報が含まれているため、Controller側で特別な処理を追加することなく、呼び出し側のURLを変えるだけで並び順を柔軟に変更できるのがこの仕組みの強みです。

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

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

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

Webアプリを公開すると、ユーザーが常にすべてのパラメータ(pageやsizeなど)を入力してくれるとは限りません。何も指定がない場合に「1ページに何件表示するか」という初期設定(デフォルト値)を決めておくことは、システムの安定稼働において非常に重要です。

Springでは@PageableDefaultアノテーションを使用することで、コントローラー層で簡単にデフォルト値を設定できます。


@GetMapping("/books/default")
public Page<Book> getBooksDefault(
        @PageableDefault(
            page = 0,               // デフォルトのページ番号(0から開始)
            size = 5,               // 1ページあたりの表示件数
            sort = "title",         // ソート対象のフィールド
            direction = Sort.Direction.ASC // 昇順(小さい順)に設定
        ) Pageable pageable) {
    
    return bookRepository.findAll(pageable);
}
プログラミング未経験者向けのイメージ例

これは、レストランの「本日のおすすめセット」のようなものです。お客さんが「何を食べたいか」を細かく指定しなかった場合に、お店側が「とりあえずこの5品を、名前順に並べてお出ししますね」と決めておく仕組みに似ています。

また、実務レベルではバリデーション(入力値チェック)も意識する必要があります。例えば、悪意のあるユーザーが「size=1000000」といった巨大な数値を指定してサーバーに負荷をかける攻撃を防ぐために、設定ファイル(application.properties)で最大取得件数を制限するなどの対策をセットで行うのがSEO的にもユーザー体験的にも優良な設計といえます。

このようにデフォルト値を適切に設定しておくことで、クエリパラメータが省略された場合でも、システムがクラッシュすることなく常に安定したレスポンスを返すことが可能になります。

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を完成させましょう!」

Spring FrameworkやThymeleafを使った Webアプリ開発の全体像をやさしく理解したい人には、 この入門書が定番です。

Spring Framework超入門をAmazonで見る

※ Amazon広告リンク

カテゴリの一覧へ
新着記事
New1
Spring
Spring の@RequestParamの使い方!テキストボックス、ラジオボタン、チェックボックス、セレクトボックスの値を受け取る。
更新記事
New2
JSP
EL式の基本構文まとめ!${}で使う書き方のルールを解説
更新記事
New3
Java
JavaのBigIntegerとisProbablePrimeメソッドを完全解説!初心者でもわかる素数判定
更新記事
New4
JSP
JSPで発生する主なエラーとは?初心者向けに原因と対処法をやさしく解説
新規投稿
人気記事
No.1
Java&Spring記事人気No1
JSP
JSPのおすすめ学習・用語まとめ【2026年最新版】初心者が知っておきたい基本をやさしく解説
No.2
Java&Spring記事人気No2
Java
Javaのクラスとインスタンス化、コンストラクタの使い方完全ガイド!初心者でもわかるオブジェクト指向の基礎
No.3
Java&Spring記事人気No3
Spring
Springの@Serviceアノテーションの使い方を徹底解説!初心者でもわかるSpring フレームワーク入門
No.4
Java&Spring記事人気No4
Spring
Thymeleaf(タイムリーフ)入門!初心者でもわかるSpring Bootとテンプレートエンジンの使い方
No.5
Java&Spring記事人気No5
Spring
Javaの@PreAuthorizeアノテーションを完全ガイド!初心者でもわかるメソッドセキュリティ設定
No.6
Java&Spring記事人気No6
Spring
Springの@Queryアノテーションを徹底解説!初心者でもわかるSpring Bootのカスタムクエリ
No.7
Java&Spring記事人気No7
Java
JavaのExceptionクラスを完全解説!初心者でも理解できる例外処理の基本
No.8
Java&Spring記事人気No8
JSP
JSPでCSSやJSを読み込む基本!外部ファイルのパス指定に注意しよう