Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
Tags
- 알파회계
- 스프링부트핵심가이드
- Kernighan의 C언어 프로그래밍
- 데비안
- network configuration
- 목록처리
- 처음 만나는 AI수학 with Python
- 리눅스
- iterator
- baeldung
- 스프링 시큐리티
- ㅒ
- /etc/network/interfaces
- d
- 구멍가게코딩단
- 티스토리 쿠키 삭제
- 처음 만나는 AI 수학 with Python
- GIT
- 자바편
- 자료구조와 함께 배우는 알고리즘 입문
- 네트워크 설정
- resttemplate
- 친절한SQL튜닝
- 선형대수
- 서버설정
- 코드로배우는스프링부트웹프로젝트
- 코드로배우는스프링웹프로젝트
- 페이징
- 자료구조와함께배우는알고리즘입문
- 이터레이터
Archives
- Today
- Total
bright jazz music
guestbook : 06. 목록처리(2) 데이터 페이지 처리 본문
● 데이터가 페이지 처리를 할 수 있도록 속성추가
- 화면에 전달되는 데이터는 PageResultDTO이다.
- 이를이용해서 화면에서 페이지 처리를 진행한다.
화면에서는 PageResultDTO를 이용하여 아래와 같이 구성한다.
- 페이지 번호를 10개씩 출력
- 1~10까지는 [이전으로] 버튼 보이지 않도록 처리
- 10페이지 이후에는 이전으로 가는 링크 생성
- 마지막 페이지의 링크 계산
1. 페이징 처리의 구성 요소
- 화면에서 시작 페이지(start)
- 화면에서 끝 페이지 번호(end)
- 이전/다음 이동 링크 여부(prev, next)
- 현재 페이지 번호(page)
- 페이징 처리를 위한 가장 중요한 정보는 사용자가 보고 있는 page 정보이다.
- 사용자가 5 페이지를 보고 있다면 페이지 번호는 1부터 시작 (pageSize를 10으로 가정)
- 사용자가 19페이지를 보고 있다면 페이지 번호는 11부터 시작 (pageSize를 10으로 가정)
페이지를 계산할 때는 끝 번호를 시작 번호보다 먼저 계산하는 것이 수월하다.
끝 번호는 아래와 같이 계산할 수 있다.(pageSize를 10으로 가정)
tempEnd = (int)(Math.ceil( 페이지번호 / 10.0)) * 10;
//Math.ceil()은 소수점을 올림으로 처리한다.
// 1페이지의 경우: Math.ceil(0.1) * 10 = 1
// 10페이지의 경우: Math.ceil(1) * 10 = 1
// 11페이지의 경우: Math.ceil(1.1) * 10 = 20
만일 화면에 10개씩 보여준다면 시작번호는 무조건 임시로 만든 끝 번호에서 9라는 값을 뺀 값이 된다.
start = tempEnd - 9;
끝 번호는 실제 마지막 페이지와 다시 비교할 필요가 있다. 예를 들어 Page<Guestbook>의 마지막 페이지가 33이라면 위의 계산에선 40이 되기 때문에 이를 반영해야 한다. 이를 위해서는 Page<Guestbook>의 getTotalPages()를 이용할 수 있다.
totalPage = result.getTotalPages(); //result는 Page<Guestbook>
end = totalPage > tempEnd ? tempEnd : totalPage;
- 이전(prev)은 시작번호(start)가 1보다 큰 경우라면 존재한다.
- 다음(next)는 realEnd가 끝 번호(End)보다 큰 경우에만 존재하게 된다.
prev = start > 1;
next = totalPage > tempEnd;
2. 페이징 처리 구성 요소를 ResultDTO에 반영
위 내용을 PageResultDTO 클래스에 반영
//PageResultDTO.java
package com.example.guestbook.dto;
import lombok.Data;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
@Data
public class PageResultDTO<DTO, EN> {
// 다양한 곳에서 사용할 수 있도록 제네릭 타입을 이용해서 DTO와 EN 타입을 지정. (EN = Entity)
//DTO리스트
private List<DTO> dtoList;
//총 페이지 번호
private int totalPage;
//현재 페이지 번호
private int page;
//목록 사이즈
private int size;
//시작 페이지 번호, 끝 페이지 번호
private int start, end;
//이전, 다음
private boolean prev, next;
//페이지 번호 목록
private List<Integer> pageList;
//PageResultDTO는 Page<Entity> 타입을 이용해서 생성할 수 있도록 생성자로 작성.
public PageResultDTO(Page<EN> result, Function<EN, DTO> fn){
//Function: 엔티티 객체들을 DTO로 변환해 주는 기능
dtoList = result.stream().map(fn).collect(Collectors.toList());
totalPage = result.getTotalPages();
makePageList(result.getPageable());
}
private void makePageList(Pageable pageable){
this.page = pageable.getPageNumber() + 1; //0부터 시작하므로 1추가
this.size = pageable.getPageSize();
//temp end page
int tempEnd = (int)(Math.ceil(page/10.0)) * 10;
start = tempEnd - 9;
prev = start > 1;
end = totalPage > tempEnd ? tempEnd : totalPage;
next = totalPage > tempEnd;
pageList = IntStream.rangeClosed(start, end).boxed()
.collect(Collectors.toList());
}
// 이와 같은 제네릭 방식을 적용하면 추후 추가적인 클래스를 작성하지 않고도 목록 데이터를 처리할 수 있다.
/*
* PageResultDTO는 List<DTO> 타입으로 DTO 객체들을 보관한다.
* 그렇기 때문에 Page<Entity>의 내용물 중에서 엔티티 객체를 DTO로 변환하는 기능이 필요하다.
* 가장 일반적인 형태는 추상 클래스를 이용해서 이를 처리하는 방식이다.
* 그러한 경우 매번 새로운 클래스가 필요하다는 단점이 있다.
*
* 이번 프로젝트의 경우 엔티티 객체의 DTO 변환은 서비스 인터페이스에 정의한
* entityToDto() 메서드와 별도로 Function객체로 만들어서 처리한다.
* */
}
3. 수정한 내용 확인하기 위해 테스트 코드 수정
PageResultDTO 클래스를 수정했으므로 GuestbookServiceTests.java의 내용도 수정하여 재 테스트
//GuestbookServiceTests.java
package com.example.guestbook.service;
import com.example.guestbook.dto.GuestbookDTO;
import com.example.guestbook.dto.PageRequestDTO;
import com.example.guestbook.dto.PageResultDTO;
import com.example.guestbook.entity.Guestbook;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class GuestbookServiceTests {
@Autowired
private GuestbookService service;
@Test
public void testRegister(){
//테스트 객체 생성
GuestbookDTO guestbookDTO = GuestbookDTO.builder()
.title("Sample title...")
.content("Sample Content...")
.writer("user0")
.build();
//service.register() 테스트: 테스트 객체 사용
System.out.println(service.register(guestbookDTO));
}
@Test
public void testList(){ //목록처리 테스트
PageRequestDTO pageRequestDTO = PageRequestDTO.builder()
.page(1)
.size(10)
.build();
PageResultDTO<GuestbookDTO, Guestbook> resultDTO = service.getList(pageRequestDTO);
//테스트에 값 확인 추가
System.out.println("PREV " + resultDTO.isPrev());
System.out.println("NEXT " + resultDTO.isNext());
System.out.println("TOTAL: " + resultDTO.getTotalPage());
for(GuestbookDTO guestbookDTO : resultDTO.getDtoList()) {
System.out.println(guestbookDTO);
}
//추가
System.out.println("====================================");
resultDTO.getPageList().forEach(i -> System.out.println(i));
}
}
테스트 결과
//console
2022-07-08 11:35:47.361 WARN 6164 --- [ Test worker] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
2022-07-08 11:35:48.544 INFO 6164 --- [ Test worker] c.e.g.service.GuestbookServiceTests : Started GuestbookServiceTests in 5.068 seconds (JVM running for 6.892)
Hibernate:
select
guestbook0_.gno as gno1_0_,
guestbook0_.moddate as moddate2_0_,
guestbook0_.reg_date as reg_date3_0_,
guestbook0_.content as content4_0_,
guestbook0_.title as title5_0_,
guestbook0_.writer as writer6_0_
from
guestbook guestbook0_
order by
guestbook0_.gno desc limit ?
Hibernate:
select
count(guestbook0_.gno) as col_0_0_
from
guestbook guestbook0_
PREV false
NEXT true
TOTAL: 31
GuestbookDTO(gno=302, title=Sample title..., content=Sample Content..., writer=user0, regDate=null, modDate=null)
GuestbookDTO(gno=301, title=Sample title..., content=Sample Content..., writer=user0, regDate=null, modDate=null)
GuestbookDTO(gno=300, title=Change Title!!!!!!!!!!!!!!!, content=change content!!!!!!!!!!!!!!!, writer=user0, regDate=null, modDate=null)
GuestbookDTO(gno=299, title=Title....299, content=Content...299, writer=user9, regDate=null, modDate=null)
GuestbookDTO(gno=298, title=Title....298, content=Content...298, writer=user8, regDate=null, modDate=null)
GuestbookDTO(gno=297, title=Title....297, content=Content...297, writer=user7, regDate=null, modDate=null)
GuestbookDTO(gno=296, title=Title....296, content=Content...296, writer=user6, regDate=null, modDate=null)
GuestbookDTO(gno=295, title=Title....295, content=Content...295, writer=user5, regDate=null, modDate=null)
GuestbookDTO(gno=294, title=Title....294, content=Content...294, writer=user4, regDate=null, modDate=null)
GuestbookDTO(gno=293, title=Title....293, content=Content...293, writer=user3, regDate=null, modDate=null)
====================================
1
2
3
4
5
6
7
8
9
10
2022-07-08 11:35:49.230 INFO 6164 --- [ionShutdownHook] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2022-07-08 11:35:49.238 INFO 6164 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated...
2022-07-08 11:35:49.252 INFO 6164 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed.
Deprecated Gradle features were used in this build, making it incompatible with Gradle 8.0.
You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.
See https://docs.gradle.org/7.4.1/userguide/command_line_interface.html#sec:command_line_warnings
BUILD SUCCESSFUL in 20s
6 actionable tasks: 5 executed, 1 up-to-date
오전 11:35:49: Task execution finished ':test --tests "com.example.guestbook.service.GuestbookServiceTests.testList"'.
'Framework > Spring' 카테고리의 다른 글
guestbook : 07. 등록페이지와 등록처리 (1) (0) | 2022.07.11 |
---|---|
guestbook : 06. 목록처리(3) 컨트롤러와 화면에서의 목록처리 (0) | 2022.07.08 |
guestbook : 06. 목록처리(1) 목록 가져오기 (0) | 2022.07.05 |
guestbook : 05. DTO를 사용한 Querydsl 테스트 (0) | 2022.07.01 |
guestbook : 04. querydsl 테스트 (0) | 2022.07.01 |
Comments