Jpa에서 제공하는 페이징기능을 이용해서 메인페이지 페이징을 해보겠다.
먼저 테스트를위해서 상품 100개를 등록하겠다.
상품등록
@SpringBootTest
class ShopApplicationTests {
@Autowired
private ItemRepository itemRepository;
@Autowired
private MemberRepository memberRepository;
@Test
void itemTest(){
for(int i=0; i<100; i++){
itemRepository.save(Item.builder()
.price(100)
.member(memberRepository.findByEmail("Seller@Seller"))
.name("test"+i)
.content("test")
.count(10)
.build());
}
}
}
100개의 상품이 등록되었다.
ItemRepository 수정
public interface ItemRepository extends JpaRepository<Item, Long> {
Page<Item> findAll(Pageable pageable);
}
findAll의 return 타입을 Page<Item>으로 변경하고
파라미터로 Pageable타입 변수를 받는다.
ItemService 수정
서비스내용을 수정해준다.
ItemService
public interface ItemService {
Page<Item> itemList(int page); // 수정
void item_reg(ItemDto itemDto, String email);
Object itemFindId(Long id);
void itemUpdate(ItemDto itemDto, Long id, Long memberId);
void delete(Long id);
}
ItemServiceImpl
@Service
@RequiredArgsConstructor
public class ItemServiceImpl implements ItemService {
private final ItemRepository itemRepository;
private final MemberRepository memberRepository;
public Page<Item> itemList(int page){
List<Sort.Order> sorts = new ArrayList<>();
sorts.add(Sort.Order.desc("id"));
Pageable pageable = PageRequest.of(page, 9, Sort.by(sorts));
return itemRepository.findAll(pageable);
}
...
id값으로 역순으로 출력해주기위해 sort해주고,
Pageable 객체를 만들어 itemReposiroty로 넘겨준다.
PageRequest.of(page, 9)에서 page는 조회할 페이지번호이고 9는 한페이지에 보여줄 게시물 갯수이다.
BoardController 수정
@Controller
@RequiredArgsConstructor
public class BoardController {
private final ItemService itemService;
@GetMapping("/")
public String index(Model model, @RequestParam(value = "page", defaultValue = "0") int page){
model.addAttribute("items", itemService.itemList(page));
return "index";
}
}
파라미터로 page값을받고 만약 page값이 없을시엔 default값으로 0을 받는다.
index.html 수정
<!DOCTYPE html>
<html lang="en" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
<title>Title</title>
<div th:replace="/fragments/header.html :: header"></div>
</head>
<body>
<div th:replace="/fragments/nav.html :: nav"></div>
<div class="container">
<h1>상품 목록</h1>
<div sec:authorize="isAuthenticated()" class="mb-2">
사용자 : <span sec:authentication="name"></span>
권한 : <span sec:authentication="authorities"></span>
</div>
<hr>
<div class="row mb-3">
<div class="col-md-4" th:each="item, loop : ${items}">
<div class="card mb-2">
<div class="card-body">
<h5 class="card-title">
<a th:href="@{/item/detail/{id}(id=${item.id})}" th:text="${item.name}"></a>
</h5>
<p class="card-text">가격: <span th:text="${item.price} + '원'"></span></p>
<p class="card-text">남은 수량: <span th:text="${item.count}"></span></p>
<p class="card-text">판매자: <span th:text="${item.member.getName()}"></span></p>
</div>
</div>
</div>
</div>
<!-- 페이지리스트 -->
<div th:if="${!items.isEmpty()}">
<ul class="pagination justify-content-center">
<li class="page-item" th:classappend="${!items.hasPrevious} ? 'disabled'">
<a class="page-link"
th:href="@{|?page=${items.number-1}|}">
<span>이전</span>
</a>
</li>
<li th:each="page: ${#numbers.sequence(0, items.totalPages-1)}"
th:if="${page >= items.number-5 and page <= items.number+5}"
th:classappend="${page == items.number} ? 'active'"
class="page-item">
<a th:text="${page+1}" class="page-link" th:href="@{|?page=${page}|}"></a>
</li>
<li class="page-item" th:classappend="${!items.hasNext} ? 'disabled'">
<a class="page-link" th:href="@{|?page=${items.number+1}|}">
<span>다음</span>
</a>
</li>
</ul>
</div>
</div>
</body>
</html>

정상적으로 작동한다.
Jpa에서 제공하는 페이징기능을 이용해서 메인페이지 페이징을 해보겠다.
먼저 테스트를위해서 상품 100개를 등록하겠다.
상품등록
@SpringBootTest
class ShopApplicationTests {
@Autowired
private ItemRepository itemRepository;
@Autowired
private MemberRepository memberRepository;
@Test
void itemTest(){
for(int i=0; i<100; i++){
itemRepository.save(Item.builder()
.price(100)
.member(memberRepository.findByEmail("Seller@Seller"))
.name("test"+i)
.content("test")
.count(10)
.build());
}
}
}
100개의 상품이 등록되었다.
ItemRepository 수정
public interface ItemRepository extends JpaRepository<Item, Long> {
Page<Item> findAll(Pageable pageable);
}
findAll의 return 타입을 Page<Item>으로 변경하고
파라미터로 Pageable타입 변수를 받는다.
ItemService 수정
서비스내용을 수정해준다.
ItemService
public interface ItemService {
Page<Item> itemList(int page); // 수정
void item_reg(ItemDto itemDto, String email);
Object itemFindId(Long id);
void itemUpdate(ItemDto itemDto, Long id, Long memberId);
void delete(Long id);
}
ItemServiceImpl
@Service
@RequiredArgsConstructor
public class ItemServiceImpl implements ItemService {
private final ItemRepository itemRepository;
private final MemberRepository memberRepository;
public Page<Item> itemList(int page){
List<Sort.Order> sorts = new ArrayList<>();
sorts.add(Sort.Order.desc("id"));
Pageable pageable = PageRequest.of(page, 9, Sort.by(sorts));
return itemRepository.findAll(pageable);
}
...
id값으로 역순으로 출력해주기위해 sort해주고,
Pageable 객체를 만들어 itemReposiroty로 넘겨준다.
PageRequest.of(page, 9)에서 page는 조회할 페이지번호이고 9는 한페이지에 보여줄 게시물 갯수이다.
BoardController 수정
@Controller
@RequiredArgsConstructor
public class BoardController {
private final ItemService itemService;
@GetMapping("/")
public String index(Model model, @RequestParam(value = "page", defaultValue = "0") int page){
model.addAttribute("items", itemService.itemList(page));
return "index";
}
}
파라미터로 page값을받고 만약 page값이 없을시엔 default값으로 0을 받는다.
index.html 수정
<!DOCTYPE html>
<html lang="en" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
<title>Title</title>
<div th:replace="/fragments/header.html :: header"></div>
</head>
<body>
<div th:replace="/fragments/nav.html :: nav"></div>
<div class="container">
<h1>상품 목록</h1>
<div sec:authorize="isAuthenticated()" class="mb-2">
사용자 : <span sec:authentication="name"></span>
권한 : <span sec:authentication="authorities"></span>
</div>
<hr>
<div class="row mb-3">
<div class="col-md-4" th:each="item, loop : ${items}">
<div class="card mb-2">
<div class="card-body">
<h5 class="card-title">
<a th:href="@{/item/detail/{id}(id=${item.id})}" th:text="${item.name}"></a>
</h5>
<p class="card-text">가격: <span th:text="${item.price} + '원'"></span></p>
<p class="card-text">남은 수량: <span th:text="${item.count}"></span></p>
<p class="card-text">판매자: <span th:text="${item.member.getName()}"></span></p>
</div>
</div>
</div>
</div>
<!-- 페이지리스트 -->
<div th:if="${!items.isEmpty()}">
<ul class="pagination justify-content-center">
<li class="page-item" th:classappend="${!items.hasPrevious} ? 'disabled'">
<a class="page-link"
th:href="@{|?page=${items.number-1}|}">
<span>이전</span>
</a>
</li>
<li th:each="page: ${#numbers.sequence(0, items.totalPages-1)}"
th:if="${page >= items.number-5 and page <= items.number+5}"
th:classappend="${page == items.number} ? 'active'"
class="page-item">
<a th:text="${page+1}" class="page-link" th:href="@{|?page=${page}|}"></a>
</li>
<li class="page-item" th:classappend="${!items.hasNext} ? 'disabled'">
<a class="page-link" th:href="@{|?page=${items.number+1}|}">
<span>다음</span>
</a>
</li>
</ul>
</div>
</div>
</body>
</html>

정상적으로 작동한다.