대덕공부/Spring

iBatis - Pagination 페이지 + 검색기능

02O2 2022. 6. 30. 21:49

PageVO

/**
 * 페이징 처리와 관련된 모든 데이터를 가진 객체 . setTotalRecord/setCurrentPage 가 호출되어야 연산 완료.
 * 
 * @param <T>
 */

@Getter
@NoArgsConstructor // 기본생성자
public class PagingVO<T> {

	public PagingVO(int screenSize, int blockSize) {
		super();
		this.screenSize = screenSize;
		this.blockSize = blockSize;
	}// 임의변경

	private int totalRecord; // DB 조회
	private int totalPage;// 토탈레코드가 결정되면 토탈페이지도 결정
	private int screenSize ; // 임의 결정
	private int blockSize ; // 임의 결정
	private int currentPage;// 사용자의 파라미터
	private int startRow;
	private int endRow;
	private int startPage;
	private int endPage;

	private List<T> dataList; // 페이징vo가 모든 데이터 갖게됨

 totalRecord : DB select했을때 갯수

totalPage : 몇개의 페이지를 만들건지

screenSize : 한페이지에 몇개의 게시글조회목록이 뜨는지 

blockSize : 이전/ 1 2 3 / 다음, 여기 블럭사이즈

currentPage 현재페이지 -> 현재페이지가 null이면 1부터시작하는거고 현재페이지=start페이지이면 사용자가 입력한 페이지가 뜨는거다 ( 2페이지 누르면 2페이지로 뜨는거)

 

/**
	 * 단순키워드 검색용
	 */
	private SimpleSearchCondition simpleCondition;
	
	public void setTotalRecord(int totalRecord) {
		this.totalRecord = totalRecord;
		this.totalPage = (totalRecord + (screenSize - 1)) / screenSize;// 서비스에서
	}

	public void setCurrentPage(int currentPage) {// 컨트롤러에서호출
		this.currentPage = currentPage;

		this.endRow = screenSize * currentPage;
		this.startRow = endRow - (screenSize - 1);
		this.endPage = ((currentPage + (blockSize - 1)) / blockSize) * blockSize;
		this.startPage = endPage - (blockSize - 1);
	}

	public void setDataList(List<T> dataList) {
		this.dataList = dataList;
	}
	
	public void setSimpleCondition(SimpleSearchCondition simpleCondition) {
		this.simpleCondition = simpleCondition;
	}

setTotalRecord(int totalRecord)

- 전체 조회 갯수가 몇개인지에 대한 setter 

-여기안에서 totalpage도 생성해준다. 

 

setCurrentPage

-currentPage 알면 startrow, endrow 계산할수있다. -> endPage, startPage도 알수있다. 

 

setDataList(List<T> dataList>

-내가 가져다 쓸 List를 제너릭T 에 반환하는 setter 예) List<MemberVO> dataList

 

setSimpleCondition

-검색기능에서 가져다 쓸 상태 setter + 추후 설명 등록 

 

	private static final String PAGINGTRN = "<a href='#' data-page='%d'>%s</a>";

	public String getPagingHTML() {
		endPage = endPage > totalPage ? totalPage : endPage;
		StringBuffer html = new StringBuffer();
		if (startPage > blockSize) {
			html.append(String.format(PAGINGTRN, (startPage - blockSize), "이전"));
		}
		for (int page = startPage; page <= endPage; page++) {
			html.append(String.format(PAGINGTRN, page, Integer.toString(page)));
		}
		if(totalPage > endPage) {
			html.append(String.format(PAGINGTRN, (endPage + 1), "다음"));
		}
		return html.toString();
	}
	
	private static final String BSPTRN = "<li class='page-item %s' %s><a class='page-link' href='#' data-page='%d'>%s</a></li>";
	
	private String makePreviousLink() {
		boolean disabled = startPage <= blockSize;
		return String.format(BSPTRN, 
							disabled?"disabled":"", 
							"", 
							startPage-blockSize, 
							"이전");
	}
	
	private String makePageLink() {
		StringBuffer pageLink = new StringBuffer();
		endPage = endPage > totalPage ? totalPage : endPage;
		for(int page=startPage; page<=endPage; page++) {
			boolean active = page == currentPage;
			pageLink.append(
				String.format(BSPTRN, 
							active?"active":"", 
							"aria-current='page'", 
							page, 
							Integer.toString(page))
			);
		}
		return pageLink.toString();
	}
	
	private String makeNextLink() {
		boolean disabled = totalPage <= endPage;
		return String.format(BSPTRN, 
							disabled?"disabled":"", 
							"", 
							endPage + 1,
							"다음");
	}
	
	public String getPagingHTMLBS() {
		StringBuffer html = new StringBuffer();
		html.append(" <nav aria-label='...'>    ");
		html.append("   <ul class='pagination'> ");
		html.append(makePreviousLink());
		html.append(makePageLink());
		html.append(makeNextLink());
		html.append("   </ul>                   ");
		html.append(" </nav>                    ");
		return html.toString();
	}                                                                                  
}

VO에서 페이징UI를 StringBuffer로 그려준다! jsp에서 el연산자로 ${paginHTMLBS}라고 쓰면 해당 값이 보여짐 !! 


MemberDAO

	public int selectTotalRecord(PagingVO<MemberVO> pagingVO);

	/**
	 * 회원목록조회 return 존재하지 않는 경우, size() ==0
	 * @param pagingVO TODO
	 */
public List<MemberVO> selectMemberList(PagingVO<MemberVO> pagingVO);

   기존 DAO에 토탈레코드가 몇개인지 조회한 "selectTotalRecord"를 만든다 이때 return값은 PagingVO<MemberVO>  - PagingVO에서 만들어준 property   private List<T> dataList; // 페이징vo가 모든 데이터 갖게됨

그러면 selectMemberList<MemberVO> return값도 PagingVO로 반환되어야한다. 

 

MemberDaoImpl

	@Override
	public List<MemberVO> selectMemberList(PagingVO<MemberVO> pagingVO) {
		try (
			SqlSession sqlSession = sqlSessionFactory.openSession();
			){
//			return sqlSession.selectList("kr.or.ddit.member.dao.MemberDAO.selectMemberList");
			
			MemberDAO mapperProxy = sqlSession.getMapper(MemberDAO.class);
			return mapperProxy.selectMemberList(pagingVO);
		}
	}
    
    	@Override
	public int selectTotalRecord(PagingVO<MemberVO> pagingVO) {
		try(
			SqlSession sqlSession = sqlSessionFactory.openSession();
			
			){
			MemberDAO mapper = sqlSession.getMapper(MemberDAO.class);
			return mapper.selectTotalRecord(pagingVO);
		}
	}

 selectTotalRecord 추가해주고 selectMemberList는 리턴값을 바꿔줌

 


MemberService

	public List<MemberVO> retrieveMemberList(PagingVO<MemberVO> pagingVO);

Dao랑 리턴값이 맞도록 바꿔준다. 

 

MemberServiceImpl

	@Override
	public List<MemberVO> retrieveMemberList(PagingVO<MemberVO> pagingVO) {
		pagingVO.setTotalRecord(memberDao.selectTotalRecord(pagingVO));
		List<MemberVO> memberList = memberDao.selectMemberList(pagingVO);
		pagingVO.setDataList(memberList);
		return memberList;
	}

마찬가지로 PagingVO<MemberVO>로 바꿔주고 

Page를 할려면 전체레코드가 몇개인지알아야하므로 pagingVo에 있는 setTotalRecord를 해주면 setTotalRecord안에서 현재페이지 시작페이지 끝페이지 페이지사이즈 등을 다 설정해줄수있기때문에 setter를 받는데 그전에 memberDao안에있는 selectTotalRecord를 통해 totalRecord를 가져온다. 


MemberListServlet

/**
 * 회원 목록을 조회하기 위한 Controller Layer
 *
 */

@WebServlet("/member/memberList.do")
public class MemberListServlet extends HttpServlet {
	MemberService service = new MemberServiceImpl();

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		req.setCharacterEncoding("UTF-8");
		String searchType = req.getParameter("searchType");
		String searchWord = req.getParameter("searchWord");
		String pageParam = req.getParameter("page");
		SimpleSearchCondition searchVO = new SimpleSearchCondition(searchType, searchWord);
		//검색조건을 하나의 객체로 묶어놓음 ,pagingVO안에 넣어야함
		
		int currentPage= 1;
		if(StringUtils.isNumeric(pageParam)) {
			currentPage=Integer.parseInt(pageParam);
		}
		
		PagingVO<MemberVO> pagingVO = new PagingVO<>(5,3);
		pagingVO.setCurrentPage(currentPage);
		pagingVO.setSimpleCondition(searchVO);
		
		service.retrieveMemberList(pagingVO);
		
		req.setAttribute("pagingVO", pagingVO);

		DelegatingViewResolver resolver = new DelegatingViewResolver();//실제로 해ㅕㄱㄹ x 또다른 resolver로 넘겨버림 
		String viewName = "/member/memberList.tiles";//member/memberList가 로직컬 뷰 네임 
		resolver.viewResolve(viewName, req, resp);
	}
}

1. setCharacterEncoding으로 인코딩부터해줌 

2. getParameter로 searchType, SerchWord //검색기능, page ( jsp에 있는 let page = $(this).data("page"); 값을 가져온다. )

3.pageParam이 숫자이면 if문안에 넣고 아니면 currentPage=1로 인식되어 첫페이지가 1이다.

4.paging의 생성자를 불러서 screenSize와 blockSize를 임의로 설정해준다.