環境
言語 : 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>
備考
- Getter・Setterはlombokを使うと簡単に追加可能。(https://projectlombok.org/)