LoginSignup
10
15

More than 3 years have passed since last update.

[Spring Boot] ページング処理簡単レシピ

Posted at

環境

言語 : java 1.8
フレームワーク : spring boot 2.2.4.RELEASE (spring-boot-starter)
テンプレートエンジン : thymeleaf 2.2.4.RELEASE (spring-boot-starter)
データベース : H2 1.4.200 (spring-boot-starter)
orm : data-jpa 2.2.4.RELEASE (spring-boot-starter)

ソースコード

Entity

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class Board {

    @Id @GeneratedValue
    private String id;

    private String title;

    private String user; 

    // Getter・Setter省略

}

Pagination

public class Pagination {

    /** 1. ページことに表示する掲示物数 **/
    private int pageSize = 10;

    /** 2. ページングした、ブロック数 **/
    private int blockSize = 10;

    /** 3. 現在ページ **/
    private int page = 1;

    /** 4. 現在ブロック **/
    private int block = 1;

    /** 5. 総掲示物数 **/
    private int totalListCnt;

    /** 6. 総ページ数 **/
    private int totalPageCnt;

    /** 7. 総ブロック数 **/
    private int totalBlockCnt;

    /** 8. ブロックスタートページ **/
    private int startPage = 1;

    /** 9. ブロック最後ページ **/
    private int endPage = 1;

    /** 10. DB接近スタートインデックス **/
    private int startIndex = 0;

    /** 11. 以前ブロックの最後ページ **/
    private int prevBlock;

    /** 12. 次のブロックの最後ページ **/
    private int nextBlock;

    // Getter・Setter省略

    public Pagination(int totalListCnt, int page) {

        // 総掲示物数と現在ページはコントローラーからもらう。
        // 総掲示物数  - totalListCnt
        // 現在ページ  - page

        /** 3. 現在ページ **/
        setPage(page);

        /** 5. 総掲示物数 **/
        setTotalListCnt(totalListCnt);

        /** 6. 総ページ数 **/
        setTotalPageCnt((int) Math.ceil(totalListCnt * 1.0 / pageSize));

        /** 7. 総ブロック数 **/
        setTotalBlockCnt((int) Math.ceil(totalPageCnt * 1.0 / blockSize));

        /** 4. 現在ブロック **/
        setBlock((int) Math.ceil((page * 1.0)/blockSize)); 

        /** 8. ブロックスタートページ **/
        setStartPage((block - 1) * blockSize + 1);

        /** 9. ブロック最後ページ **/
        setEndPage(startPage + blockSize - 1);

        /* === ブラック最後ページについてバリエーション ===*/
        if(endPage > totalPageCnt){this.endPage = totalPageCnt;}

        /** 11. 以前ブロックの最後ページ **/
        setPrevBlock((block * blockSize) - blockSize);

        /* === 以前ブロックについてバリエーション === */
        if(prevBlock < 1) {this.prevBlock = 1;}

        /** 12. 次のブロックの最後ページ **/
        setNextBlock((block * blockSize) + 1);

        /* === 次のブロックについてバリエーション ===*/
        if(nextBlock > totalPageCnt) {nextBlock = totalPageCnt;}

        /** 10. DB接近スタートインデックス **/
        setStartIndex((page-1) * pageSize);

    }
}

Controller

@GetMapping("/")
public String home(Model model, @RequestParam(defaultValue = "1") int page) {

    // 総掲示物数 
    int totalListCnt = boardRepository.findAllCnt();

    // 総掲示物数と現在ページ
    Pagination pagination = new Pagination(totalListCnt, page);

    // DB接近スタートインデックス
    int startIndex = pagination.getStartIndex();

    // ページことに表示する掲示物最大数
    int pageSize = pagination.getPageSize();

    // 掲示物取得
    List<Board> boardList = boardRepository.findListPaging(startIndex, pageSize);

    // モデルオブジェクトにオブジェクト格納
    model.addAttribute("boardList", boardList);
    model.addAttribute("pagination", pagination);

    return "index";
}

Repository

@Repository
public class BoardRepository {

    @PersistenceContext
    private EntityManager em;

    public int findAllCnt() {
        return ((Number) em.createQuery("select count(*) from Board")
                    .getSingleResult()).intValue();
    }

    public List<Board> findListPaging(int startIndex, int pageSize) {
        return em.createQuery("select b from Board b", Board.class)
                    .setFirstResult(startIndex)
                    .setMaxResults(pageSize)
                    .getResultList();
    }
}

html

<!DOCTYPE html>
<html   lang="ja" 
        xmlns="http://www.w3.org/1999/xhtml" 
        xmlns:th="http://www.thymeleaf.org">

<head>
    <meta charset="UTF-8">
    <title>paging</title>
        <link rel="stylesheet" th:href="@{/css/bootstrap.min.css}">
    </head>
<body>

<table class="table table-striped">

  <thead class="thead-dark">
    <tr>
      <th scope="col" style="width: 10%">no</th>
      <th scope="col">title</th>
      <th scope="col" style="width: 15%">user</th>
    </tr>
  </thead>

  <tbody>
    <tr th:each="board : ${boardList}">
      <th scope="row" th:text="${boardStat.index + 1}">1</th>
      <td th:text="${board.title}"></td>
      <td th:text="${board.user}"></td>
    </tr>
  </tbody>

</table>

// ページング
<nav aria-label="Page navigation example ">
  <ul class="pagination">
  <li class="page-item">
      <a class="page-link" th:href="@{/?page=1}" aria-label="Previous">
        <span aria-hidden="true"><<</span>
      </a>
    </li>
    <li class="page-item">
      <a class="page-link" th:href="@{/?page={page} (page = ${pagination.prevBlock})}" aria-label="Previous">
        <span aria-hidden="true"></span>
      </a>
    </li>
    <th:block  th:with="start = ${pagination.startPage}, end = ${pagination.endPage}">
        <li class="page-item" 
                 th:with="start = ${pagination.startPage}, end = ${pagination.endPage}"
                th:each="pageButton : ${#numbers.sequence(start, end)}">
                <a class="page-link" th:href="@{/?page={page} (page = ${pageButton})}" th:text=${pageButton}></a>
        </li>
    </th:block>
    <li class="page-item">
      <a class="page-link" th:href="@{?page={page} (page = ${pagination.nextBlock})}" aria-label="Next">
        <span aria-hidden="true"></span>
      </a>
    </li>
    <li class="page-item">
      <a class="page-link" th:href="@{?page={page} (page = ${pagination.totalPageCnt})}" aria-label="Previous">
        <span aria-hidden="true">>></span>
      </a>
    </li>
  </ul>
</nav>

</body>
</html>

備考

10
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
15