페이징 시 알아두면 좋을 용어
페이징처리
연산식 구하기
총 페이지 수 연산(totalPage):
- totalRecord % screenSize== 0? totalRecord/ screenSize: totalRecord/ screenSize + 1
시작게시물번호 연산(startRow):
- startRow = (currentPage -1) * screenSize + 1;
- endRow = currentPage * screenSize;
시작페이지 연산(startPage):
- endPage = (currentPage + (blockSize - 1)) / blockSize * blockSize;
- startPage = endPage - (blockSize -1);
필요 요소
- totalPage는 totalRecord의 값을 알아야 구할 수 있다.
- startRow, startPage 두개 모두 currentPage를 알아야 구할 수 있다.
VO에서 값을 가져간다 → db에 해당 쿼리문 실행 → 값을 다시 vo로
코드(PagingVO)
package kr.or.ddit.vo; import static org.junit.Assume.assumeNoException; import java.io.Serializable; import java.util.List; import java.util.Set; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @Setter @Getter @NoArgsConstructor // 기본생성자 public class PagingVO<T> implements Serializable{ public PagingVO(int screenSize, int blockSize) { super(); this.screenSize = screenSize; this.blockSize = blockSize; } private int totalRecord; private int screenSize = 10; private int blockSize = 5; private int currentPage; private int totalPage; private int startRow; private int endRow; private int startPage; private int endPage; private List<T> dataList; private SearchVO simpleSearch; public void setTotalRecord(int totalRecord) { this.totalRecord = totalRecord; totalPage = totalRecord % screenSize == 0? totalRecord/screenSize : totalRecord/screenSize +1; } public void setCurrentPage(int currentPage) { this.currentPage = currentPage; startRow = (currentPage - 1)*screenSize + 1; endRow = currentPage * screenSize; endPage = (currentPage + (blockSize-1))/blockSize * blockSize; startPage = endPage - (blockSize - 1); } private static String aPattern = "<a href='#' data-page = '%d'>[%s]</a>"; private static String currentPagePtrn = "<a href='#'>[%s]</a>"; public String getPagingHTML() { StringBuffer html = new StringBuffer(); if(startPage > 1) { html.append( String.format(aPattern, (startPage-1), "이전") ); } endPage = endPage < totalPage ? endPage : totalPage; for(int page=startPage; page<=endPage; page++) { if(page == currentPage) { html.append( String.format(currentPagePtrn, page+"") ); }else { html.append( String.format(aPattern, page, page+"") ); } } if(endPage < totalPage) { html.append( String.format(aPattern, (endPage +1), "다음") ); } return html.toString(); } }
코드(member.xml)
<sql id="searchFrag"> <where> <if test="simpleSearch!=null and @org.apache.commons.lang3.StringUtils@isNotBlank(simpleSearch.searchWord)"> <choose> <when test="simpleSearch.searchType eq 'name'"> INSTR(MEM_NAME, #{simpleSearch.searchWord}) > 0 </when> <when test="simpleSearch.searchType eq 'address'"> INSTR(MEM_ADD1, #{simpleSearch.searchWord}) > 0 </when> <otherwise> INSTR(MEM_NAME, #{simpleSearch.searchWord}) > 0 OR INSTR(MEM_ADD1, #{simpleSearch.searchWord}) > 0 </otherwise> </choose> </if> </where> </sql> <select id="selectMemberList" resultType="memberVO" parameterType="PagingVO" > SELECT B.* FROM( SELECT A.*, ROWNUM RNUM FROM( SELECT ROWID RID, mem_id, mem_pass, mem_name, mem_mail , MEM_ADD1 FROM member <include refid="searchFrag" /> ORDER BY RID DESC ) A ) B <![CDATA[ WHERE RNUM >= #{startRow} AND RNUM <= #{endRow} ]]> </select> <select id="selectTotalRecord" resultType = "int" parameterType ="PagingVO"> SELECT COUNT(*) FROM MEMBER <include refid="searchFrag" /> </select>
MemberDAOImpl.java
package kr.or.ddit.member.dao; import java.util.List; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import kr.or.ddit.db.mybatis.CustomSqlSessionFactoryBuilder; import kr.or.ddit.vo.MemberVO; import kr.or.ddit.vo.PagingVO; public class MemberDAOImpl implements IMemberDAO { // 싱글톤 만들기 private static MemberDAOImpl self; private MemberDAOImpl() {} public static MemberDAOImpl getInstance() { if(self==null) self = new MemberDAOImpl(); return self; } private SqlSessionFactory sessionFactory = CustomSqlSessionFactoryBuilder.getSessionFactory(); @Override public MemberVO selectMemberForAuth(String mem_id) { try( SqlSession session = sessionFactory.openSession(); ){ // return (MemberVO) session.selectOne("kr.or.ddit.member.dao.IMemberDAO.selectMemberForAuth", mem_id); // mapper proxy - 가짜 매퍼 IMemberDAO mapper = session.getMapper(IMemberDAO.class); return mapper.selectMemberForAuth(mem_id); } } @Override public MemberVO selectMemberDetail(String mem_id) { try( SqlSession session = sessionFactory.openSession(); ){ IMemberDAO mapper = session.getMapper(IMemberDAO.class); return mapper.selectMemberDetail(mem_id); } } @Override public int insertMember(MemberVO member) { try( SqlSession session = sessionFactory.openSession(); ){ IMemberDAO mapper = session.getMapper(IMemberDAO.class); int cnt = mapper.insertMember(member); session.commit(); return cnt; } } @Override public int updateMember(MemberVO member) { try( SqlSession session = sessionFactory.openSession(); // 문제가 있다. 문제가 있어도 commit을 해버림 ){ // MemberDAOImpl.class.equals(this.getClass()); IMemberDAO mapper = session.getMapper(IMemberDAO.class); int cnt = mapper.updateMember(member); session.commit(); return cnt; } } @Override public int deleteMember(String mem_id) { try( SqlSession session = sessionFactory.openSession(); ){ IMemberDAO mapper = session.getMapper(IMemberDAO.class); int cnt = mapper.deleteMember(mem_id); session.commit(); return cnt; } } @Override public List<MemberVO> selectMemberList(PagingVO pagingVO) { try( SqlSession session = sessionFactory.openSession(); // 문제가 있다. 문제가 있어도 commit을 해버림 ){ // MemberDAOImpl.class.equals(this.getClass()); IMemberDAO mapper = session.getMapper(IMemberDAO.class); return mapper.selectMemberList(pagingVO); } } @Override public int selectTotalRecord(PagingVO pagingVO) { try( SqlSession session = sessionFactory.openSession(); // 문제가 있다. 문제가 있어도 commit을 해버림 ){ // MemberDAOImpl.class.equals(this.getClass()); IMemberDAO mapper = session.getMapper(IMemberDAO.class); return mapper.selectTotalRecord(pagingVO); } } }
MemberServiceImpl.java
package kr.or.ddit.member.service; import java.lang.reflect.InvocationTargetException; import java.util.List; import org.apache.commons.beanutils.BeanUtils; import kr.or.ddit.enumpkg.ServiceResult; import kr.or.ddit.member.UserNotFoundException; import kr.or.ddit.member.dao.IMemberDAO; import kr.or.ddit.member.dao.MemberDAOImpl; import kr.or.ddit.vo.MemberVO; import kr.or.ddit.vo.PagingVO; public class MemberServiceImpl implements IMemberService { private IMemberDAO dao = MemberDAOImpl.getInstance(); private IAuthenticateService authService = new AuthenticateServiceImpl(); @Override public MemberVO retrieveMember(String mem_id) { MemberVO savedMember = dao.selectMemberDetail(mem_id); if (savedMember == null) { // custom exception 발생 // compile error가 발생하면 checked exception이다. ex)Exceiption() throw new UserNotFoundException("아이디에 해당하는 회원이 존재하지 않음."); } return savedMember; // 특정 상황에 쓸 수 있는 커스텀 익셉션 } @Override public ServiceResult createMember(MemberVO member) { ServiceResult result = null; if (dao.selectMemberDetail(member.getMem_id()) == null) { // 중복되지 않는다면 int rowcnt = dao.insertMember(member); if (rowcnt > 0) { // 성공 result = ServiceResult.OK; } else { // 실패 result = ServiceResult.FAIL; } } else { // 중복 result = ServiceResult.PKDUPLICATED; } return result; } @Override public ServiceResult modifyMember(MemberVO member) { retrieveMember(member.getMem_id()); ServiceResult result = authService.authenticate(new MemberVO(member.getMem_id(), member.getMem_pass())); if (ServiceResult.OK.equals(result)) { int rowcnt = dao.updateMember(member); if (rowcnt > 0) { result = ServiceResult.OK; } else { result = ServiceResult.FAIL; } } return result; } @Override public ServiceResult removeMember(MemberVO member) { retrieveMember(member.getMem_id()); ServiceResult result = authService.authenticate(new MemberVO(member.getMem_id(), member.getMem_pass())); if (ServiceResult.OK.equals(result)) { int rowcnt = dao.deleteMember(member.getMem_id()); if (rowcnt > 0) { result = ServiceResult.OK; } else { result = ServiceResult.FAIL; } } return result; } @Override public List<MemberVO> retrieveMemberList(PagingVO pagingVO) { return dao.selectMemberList(pagingVO); } @Override public int retrieveMemberCount(PagingVO<MemberVO> pagingVO) { return dao.selectTotalRecord(pagingVO); } }
MemberListServlet.java
package kr.or.ddit.member.controller; import java.io.IOException; import java.util.List; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import kr.or.ddit.member.service.IMemberService; import kr.or.ddit.member.service.MemberServiceImpl; import kr.or.ddit.vo.MemberVO; import kr.or.ddit.vo.PagingVO; import kr.or.ddit.vo.SearchVO; @WebServlet("/member/memberList.do") public class MemberListServlet extends HttpServlet { IMemberService 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"); SearchVO searchVO = new SearchVO(searchType, searchWord); String pageParam = req.getParameter("page"); int currentPage = 1; if(pageParam!=null && pageParam.matches("\\d+")) { currentPage = Integer.parseInt(pageParam); } PagingVO<MemberVO> pagingVO = new PagingVO(7, 2); pagingVO.setCurrentPage(currentPage); // 검색 조건 먼저 담아주어야함. pagingVO.setSimpleSearch(searchVO); int totalRecord = service.retrieveMemberCount(pagingVO); pagingVO.setTotalRecord(totalRecord); List<MemberVO> memberList = service.retrieveMemberList(pagingVO); pagingVO.setDataList(memberList); req.setAttribute("pagingVO", pagingVO); String view = "/WEB-INF/views/member/memberList.jsp"; req.getRequestDispatcher(view).forward(req, resp); } }
memberList.jsp
<%@page import="kr.or.ddit.vo.SearchVO"%> <%@page import="kr.or.ddit.vo.PagingVO"%> <%@page import="kr.or.ddit.vo.MemberVO"%> <%@page import="java.util.List"%> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> <jsp:include page = "/includee/preScript.jsp" /> </head> <body> <h4>회원 목록 조회</h4> <table border= '1'> <thead> <tr> <th>No.</th> <th>회원아이디</th> <th>회원명</th> <th>이메일</th> <th>휴대폰</th> <th>마일리지</th> <th>탈퇴여부</th> <th>지역</th> </tr> </thead> <tbody> <% PagingVO<MemberVO> pagingVO = (PagingVO) request.getAttribute("pagingVO"); List<MemberVO> memberList = pagingVO.getDataList(); if(memberList.size()>0){ for(MemberVO member : memberList){ %> <tr> <td><%=member.getRnum() %></td> <td><%=member.getMem_id() %></td> <td><%=member.getMem_name() %></td> <td><%=member.getMem_mail() %></td> <td><%=member.getMem_hp() %></td> <td><%=member.getMem_mileage()%></td> <td> <%="Y".equals(member.getMem_delete())?"탈퇴" : "" %> </td> <td><%=member.getMem_add1()%></td> </tr> <% } }else{ %> <tr> <td colspan="5"> 등록된 데이터 없음. <% } %> </tbody> <tfoot> <tr> <td colspan="6"> <form id = "searchForm"> <input type = "text" name = "searchType" value="${pagingVO.simpleSearch.searchType }"/> <input type = "text" name = "searchWord" value="${pagingVO.simpleSearch.searchWord }"/> <input type = "text" name = "page" /> </form> <div id = "searchUI"> <select name = "searchType"> <option value>전체</option> <option value="name">이름</option> <option value="address">지역</option> </select> <input type = "text" name = "searchWord" value="${pagingVO.simpleSearch.searchWord }" /> <input id = "searchBtn" type = "button" value = "검색" /> </div> <div id = "pagingArea"> <%=pagingVO.getPagingHTML() %> </div> </td> </tr> </tfoot> </table> <script type = "text/javascript"> let searchForm = $("#searchForm"); let searchUI = $("#searchUI"); searchUI.find("[name='searchType']").val("${pagingVO.simpleSearch.searchType }"); $("#searchBtn").on("click", function(){ let inputs = searchUI.find(":input[name]"); $(inputs).each(function(idx, input){ let name = $(this).attr("name"); let sameInput = searchForm.find("[name='"+name+"']") $(sameInput).val($(this).val()); }); searchForm.submit(); }); $("#pagingArea").on("click", "a", function(event){ event.preventDefault(); let page = $(this).data("page"); if(page){ searchForm.find("[name='page']").val(page); searchForm.submit(); } return false; }); </script> </body> </html>
*알면 좋은 단축키들 - alt +shift+c
- 해당 인스턴스 파라미터 변경하기. preview로 무엇이 영향을 받는지 알 수 있다.
HAS A 관계에서는 꼭 result Map을 꼭 쓰지 않아도 된다.
- has a → association
- has many → collections
strict alias를 잘 쓰면 된다.
**추가
.find(":input[name]") 분석
: 모든 input 태그
[name] name을 가지고 있는 모든 input 태그.
data-page로 값 찾기.
ogln과 el의 문법은 거의 비슷하다.
Uploaded by Notion2Tistory v1.1.0