페이징 처리
https://adminlte.io/themes/v3/pages/tables/jsgrid.html
접속해서 페이징부분 해당 태그 가져오기
<div class="jsgrid-pager-container">
<div class="jsgrid-pager">
Pages:
<span class="jsgrid-pager-nav-button jsgrid-pager-nav-inactive-button">
<a href="javascript:void(0);">First</a></span>
<span class="jsgrid-pager-nav-button jsgrid-pager-nav-inactive-button">
<a href="javascript:void(0);">Prev</a></span>
<span class="jsgrid-pager-page jsgrid-pager-current-page">1</span>
<span class="jsgrid-pager-page"><a href="javascript:void(0);">2</a></span>
<span class="jsgrid-pager-page"><a href="javascript:void(0);">3</a></span>
<span class="jsgrid-pager-page"><a href="javascript:void(0);">4</a></span>
<span class="jsgrid-pager-page"><a href="javascript:void(0);">5</a></span>
<span class="jsgrid-pager-nav-button"><a href="javascript:void(0);">Next</a></span>
<span class="jsgrid-pager-nav-button"><a href="javascript:void(0);">Last</a></span>
1 of 5
</div>
</div>
페이징 적용 확인
아래 해당 코드 추가
<!-- jsGrid -->
<link rel="stylesheet" href="/resources/css/jsgrid.min.css">
<link rel="stylesheet" href="/resources/css/jsgrid-theme.min.css">
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!-- jsGrid -->
<link rel="stylesheet" href="/resources/css/jsgrid.min.css">
<link rel="stylesheet" href="/resources/css/jsgrid-theme.min.css">
<script type="text/javascript" src="/resources/js/jquery.min.js"></script>
<script type="text/javascript">
$(function(){
$("#comCode").on("change",function(){
console.log("comCode : " + $(this).val());
console.log("comCodeNm : " + $(this).children("option:selected").text());
let comCode = $(this).val();
location.href = "/comCode/comCodeList?comCode="+comCode;
});
});
</script>
<div class="row">
<div class="col-sm-4">
<!-- action이 없으면 현재 URL. method가 없으면 기본이 get
요청URI : /comCode/comCodeList?comCode=A07&comCodeDetNm=교부
요청파라미터 : comCode=A07&comCodeDetNm=교부
요청방식 : get
-->
<form>
<select class="form-select" id="comCode" name="comCode"
aria-label="Default select example">
<option value="" selected>공통코드</option>
<!-- model.addAttribute("data", comCodeVOList);
data : List<ComCodeVO>
-->
<c:forEach var="comCodeVO" items="${data}" varStatus="stat0">
<option value="${comCodeVO.comCode}"
<c:if test="${param.comCode==comCodeVO.comCode}">selected</c:if>
>${comCodeVO.comCodeNm}</option>
</c:forEach>
</select>
</div>
<div class="col-sm-5">
<input type="text" class="form-control" name="comCodeDetNm" id="comCodeDetNm"
value="${param.comCodeDetNm}" placeholder="공통상세명" />
</div>
<div class="col-sm-3">
<button type="submit" class="btn btn-primary m-1">검색</button>
</div>
</form>
</div>
<hr />
<div class="row">
<div class="col-sm-6 mb-3 mb-sm-0">
<div class="card">
<div class="card-header">
공통 코드
</div>
<div class="card-body">
<!-- ///// 공통 코드 목록 시작 ///// -->
<table class="table">
<thead>
<tr>
<th scope="col">공통 코드</th>
<th scope="col">공통 코드 명</th>
</tr>
</thead>
<tbody>
<!-- model.addAttribute("comCodeVOList", comCodeVOList) -->
<c:forEach var="comCodeVO" items="${comCodeVOList}" varStatus="stat">
<tr>
<th scope="row"><a href="/comCode/comCodeList?comCode=${comCodeVO.comCode}">${comCodeVO.comCode}</a></th>
<td>${comCodeVO.comCodeNm}</td>
</tr>
</c:forEach>
</tbody>
</table>
<!-- ///// 공통 코드 목록 끝 ///// -->
</div>
<div class="jsgrid-pager-container text-center">
<div class="jsgrid-pager">
<span class="jsgrid-pager-nav-button jsgrid-pager-nav-inactive-button">
<a href="javascript:void(0);">Prev</a>
</span>
<span class="jsgrid-pager-page jsgrid-pager-current-page">1</span>
<span class="jsgrid-pager-page"><a href="javascript:void(0);">2</a></span>
<span class="jsgrid-pager-page"><a href="javascript:void(0);">3</a></span>
<span class="jsgrid-pager-page"><a href="javascript:void(0);">4</a></span>
<span class="jsgrid-pager-page"><a href="javascript:void(0);">5</a></span>
<span class="jsgrid-pager-nav-button"><a href="javascript:void(0);">Next</a></span>
</div>
</div>
</div>
</div>
<div class="col-sm-6">
<div class="card">
<div class="card-header">
공통 코드 상세
</div>
<div class="card-body">
<!-- ///// 공통 코드 상세 목록 시작 ///// -->
<table class="table">
<thead>
<tr>
<th scope="col">공통 코드 상세</th>
<th scope="col">공통 코드 상세 명</th>
<th scope="col">공통 코드</th>
</tr>
</thead>
<tbody>
<c:forEach var="comCodeDetVO" items="${comCodeDetVOList}" varStatus="stat">
<tr>
<th scope="row">${comCodeDetVO.comCodeDet}</th>
<td>${comCodeDetVO.comCodeDetNm}</td>
<td>${comCodeDetVO.comCode}</td>
</tr>
</c:forEach>
</tbody>
</table>
<!-- ///// 공통 코드 상세 목록 끝 ///// -->
</div>
</div>
</div>
</div>
util 패키지 생성 , ArticlePage , MiniPage 클래스 생성
package kr.or.ddit.util;
import java.util.List;
// 페이징 관련 정보 + 게시글 정보
// new ArticlePage<FreeBoardVO>(total, currentPage, size, content);
public class MiniPage<T> {
// 전체글 수
private int total;
// 현재 페이지 번호
private int currentPage;
// 전체 페이지수
private int totalPages;
// 블록의 시작 페이지 번호
private int startPage;
// 블록의 종료 페이지 번호
private int endPage;
//검색어
private String keyword = "";
//요청URL
private String url = "";;
//select 결과 데이터
private List<T> content;
// 페이징 처리
private String pagingArea = "";
// 블록크기
private int blockSize = 3;
// 생성자(Constructor) : 페이징 정보를 생성
// 753 1 10 select 결과 => 10행
public MiniPage(int total, int currentPage, int size, List<T> content, String keyword) {
//size : 한 화면에 보여질 목록의 행 수
this.total = total;//753
this.currentPage = currentPage;//1
this.content = content;
this.keyword = keyword;
//전체글 수가 0이면?
if(total == 0) {
totalPages = 0;//전체 페이지 수
startPage = 0;//블록 시작번호
endPage = 0; //블록 종료번호
} else {//글이 있다면
//전체 페이지 수 = 전체글 수 / 한 화면에 보여질 목록의 행 수
//3 = 31 / 10
totalPages = total / size;//75
//나머지가 있다면, 페이지를 1 증가
if(total % size > 0) {//나머지3
totalPages++;//76
}
// 페이지 블록 시작번호를 구하는 공식
// 블록시작번호 = 현재페이지 / 페이지크기 * 페이지크기 + 1
startPage = currentPage / blockSize * blockSize + 1;//1
//현재페이지 % 페이지크기 => 0일 때 보정
if(currentPage % blockSize == 0) {
startPage -= blockSize;
}
//블록종료번호 = 시작페이지번호 + (페이지크기 - 1)
//[1][2][3][4][5][다음]
endPage = startPage + (blockSize - 1);//5
//종료페이지번호 > 전체페이지수
if(endPage > totalPages) {
endPage = totalPages;
}
}
pagingArea += "<div class='col-sm-12 col-md-7'>";
pagingArea += "<div class='dataTables_paginate paging_simple_numbers' id='example2_paginate'>";
pagingArea += "<ul class='pagination'>";
pagingArea += "<li class='paginate_button page-item previous ";
if(this.startPage < 4) {
//
pagingArea += "disabled";
}
pagingArea += "'";
pagingArea += " id='example2_previous'>";
pagingArea += "<a href='"+this.url+"?currentPage="+(this.startPage-blockSize)+"&keyword="+this.keyword+"' aria-controls='example2' data-dt-idx='0' tabindex='0'";
// startPage에서 blockSize만큼 뺀다
pagingArea += "class='page-link'>Previous</a></li>";
for(int pNo=this.startPage;pNo<=this.endPage;pNo++) {
pagingArea += "<li class='paginate_button page-item ";
if(this.currentPage == pNo) {
pagingArea += "active";
}
pagingArea += "'>";
pagingArea += "<a href='"+this.url+"?currentPage="+pNo+"&keyword="+this.keyword+"' aria-controls='example2' data-dt-idx='1' tabindex='0'";
pagingArea += "class='page-link'>"+pNo+"</a>";
pagingArea += "</li>";
}
pagingArea += "<li class='paginate_button page-item next ";
if(this.endPage>=this.totalPages) {
pagingArea += "disabled";
}
pagingArea += "' id='example2_next'><a ";
pagingArea += "href='"+this.url+"?currentPage="+(this.startPage+blockSize)+"&keyword="+this.keyword+"' aria-controls='example2' data-dt-idx='7' ";
// 블록사이즈를 더해주면 다음 블록으로 이동
pagingArea += "tabindex='0' class='page-link'>Next</a></li>";
pagingArea += "</ul>";
pagingArea += "</div>";
pagingArea += "</div>";
}//end 생성자
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
public int getCurrentPage() {
return currentPage;
}
public void setCurrentPage(int currentPage) {
this.currentPage = currentPage;
}
public int getTotalPages() {
return totalPages;
}
public void setTotalPages(int totalPages) {
this.totalPages = totalPages;
}
public int getStartPage() {
return startPage;
}
public void setStartPage(int startPage) {
this.startPage = startPage;
}
public int getEndPage() {
return endPage;
}
public void setEndPage(int endPage) {
this.endPage = endPage;
}
public String getKeyword() {
return keyword;
}
public void setKeyword(String keyword) {
this.keyword = keyword;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public List<T> getContent() {
return content;
}
public void setContent(List<T> content) {
this.content = content;
}
//전체 글의 수가 0인가?
public boolean hasNoArticles() {
return this.total == 0;
}
//데이터가 있나?
public boolean hasArticles() {
return this.total > 0;
}
//페이징 블록을 자동화
public String getPagingArea() {
return this.pagingArea;
}
public void setPagingArea(String pagingArea) {
this.pagingArea = pagingArea;
}
public int getBlockSize() {
return blockSize;
}
public void setBlockSize(int blockSize) {
this.blockSize = blockSize;
}
}
ComCodeController내 comCodeList메소드 수정(변수 추가)
//공통 코드 목록
/*
요청URI : /comCode/comCodeList?comCode=A07&comCodeDetNm=교부¤tPage=3
요청파라미터 : comCode=A07&comCodeDetNm=교부
요청방식 : get
*/
@GetMapping("/comCodeList")
public String comCodeList(Model model,
@RequestParam(value = "comCode" , required = false ,defaultValue = "" ) String comCode,
@RequestParam(value = "comCodeDetNm" , required = false , defaultValue = "") String comCodeDetNm,
@RequestParam(value = "currentPage" , required = false , defaultValue = "1") int currentPage) {
log.info("comCodeList -> comCode : " + comCode);
log.info("comCodeList -> comCodeDetNm : " + comCodeDetNm);
// 공통 코드 목록
List<ComCodeVO> comCodeVOList = this.comCodeService.comCodeList();
log.info("comCodeVOList : " + comCodeVOList);
// 공통 코드 상세 목록
Map<String , Object> map = new HashMap<String, Object>();
map.put("comCode", comCode);
map.put("comCodeDetNm" , comCodeDetNm);
List<ComCodeDetVO> comCodeDetVOList = this.comCodeService.comCodeDetVOList(map);
// 공통 코드 목록에 대한 페이징 처리
MiniPage<ComCodeVO> miniPage = new MiniPage<ComCodeVO>(total, currentPage, 5, comCodeVOList, comCode , comCodeDetNm);
model.addAttribute("comCodeVOList" , comCodeVOList);
model.addAttribute("comCodeDetVOList" , comCodeDetVOList);
// forwarding : jsp
return "admin/comCodeList";
}
MiniPage클래스 수정
package kr.or.ddit.util;
import java.util.List;
// 페이징 관련 정보 + 게시글 정보
// new ArticlePage<FreeBoardVO>(total, currentPage, size, content);
public class MiniPage<T> {
// 전체글 수
private int total;
// 현재 페이지 번호
private int currentPage;
// 전체 페이지수
private int totalPages;
// 블록의 시작 페이지 번호
private int startPage;
// 블록의 종료 페이지 번호
private int endPage;
//검색어
private String keyword = "";
//요청URL
private String url = "";;
//select 결과 데이터
private List<T> content;
// 페이징 처리
private String pagingArea = "";
// 블록크기
private int blockSize = 3;
// 공통 코드[검색조건]
private String comCode;
// 공통 코드 상세 명[검색조건]
private String comCodeDetNm;
// 생성자(Constructor) : 페이징 정보를 생성
// 753 1 10 select결과 =>10행 , comCode , comCodeDetNm
public MiniPage(int total, int currentPage, int size, List<T> content, String comCode , String comCodeDetNm) {
//size : 한 화면에 보여질 목록의 행 수
this.total = total;//753
this.currentPage = currentPage;//1
this.content = content;
this.keyword = keyword;
//전체글 수가 0이면?
if(total == 0) {
totalPages = 0;//전체 페이지 수
startPage = 0;//블록 시작번호
endPage = 0; //블록 종료번호
} else {//글이 있다면
//전체 페이지 수 = 전체글 수 / 한 화면에 보여질 목록의 행 수
//3 = 31 / 10
totalPages = total / size;//75
//나머지가 있다면, 페이지를 1 증가
if(total % size > 0) {//나머지3
totalPages++;//76
}
// 페이지 블록 시작번호를 구하는 공식
// 블록시작번호 = 현재페이지 / 페이지크기 * 페이지크기 + 1
startPage = currentPage / blockSize * blockSize + 1;//1
//현재페이지 % 페이지크기 => 0일 때 보정
if(currentPage % blockSize == 0) {
startPage -= blockSize;
}
//블록종료번호 = 시작페이지번호 + (페이지크기 - 1)
//[1][2][3][4][5][다음]
endPage = startPage + (blockSize - 1);//5
//종료페이지번호 > 전체페이지수
if(endPage > totalPages) {
endPage = totalPages;
}
}
pagingArea += "<div class='col-sm-12 col-md-7'>";
pagingArea += "<div class='dataTables_paginate paging_simple_numbers' id='example2_paginate'>";
pagingArea += "<ul class='pagination'>";
pagingArea += "<li class='paginate_button page-item previous ";
if(this.startPage < 4) {
//
pagingArea += "disabled";
}
pagingArea += "'";
pagingArea += " id='example2_previous'>";
pagingArea += "<a href='"+this.url+"?currentPage="+(this.startPage-blockSize)+"&keyword="+this.keyword+"' aria-controls='example2' data-dt-idx='0' tabindex='0'";
// startPage에서 blockSize만큼 뺀다
pagingArea += "class='page-link'>Previous</a></li>";
for(int pNo=this.startPage;pNo<=this.endPage;pNo++) {
pagingArea += "<li class='paginate_button page-item ";
if(this.currentPage == pNo) {
pagingArea += "active";
}
pagingArea += "'>";
pagingArea += "<a href='"+this.url+"?currentPage="+pNo+"&keyword="+this.keyword+"' aria-controls='example2' data-dt-idx='1' tabindex='0'";
pagingArea += "class='page-link'>"+pNo+"</a>";
pagingArea += "</li>";
}
pagingArea += "<li class='paginate_button page-item next ";
if(this.endPage>=this.totalPages) {
pagingArea += "disabled";
}
pagingArea += "' id='example2_next'><a ";
pagingArea += "href='"+this.url+"?currentPage="+(this.startPage+blockSize)+"&keyword="+this.keyword+"' aria-controls='example2' data-dt-idx='7' ";
// 블록사이즈를 더해주면 다음 블록으로 이동
pagingArea += "tabindex='0' class='page-link'>Next</a></li>";
pagingArea += "</ul>";
pagingArea += "</div>";
pagingArea += "</div>";
}//end 생성자
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
public int getCurrentPage() {
return currentPage;
}
public void setCurrentPage(int currentPage) {
this.currentPage = currentPage;
}
public int getTotalPages() {
return totalPages;
}
public void setTotalPages(int totalPages) {
this.totalPages = totalPages;
}
public int getStartPage() {
return startPage;
}
public void setStartPage(int startPage) {
this.startPage = startPage;
}
public int getEndPage() {
return endPage;
}
public void setEndPage(int endPage) {
this.endPage = endPage;
}
public String getKeyword() {
return keyword;
}
public void setKeyword(String keyword) {
this.keyword = keyword;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public List<T> getContent() {
return content;
}
public void setContent(List<T> content) {
this.content = content;
}
//전체 글의 수가 0인가?
public boolean hasNoArticles() {
return this.total == 0;
}
//데이터가 있나?
public boolean hasArticles() {
return this.total > 0;
}
//페이징 블록을 자동화
public String getPagingArea() {
return this.pagingArea;
}
public void setPagingArea(String pagingArea) {
this.pagingArea = pagingArea;
}
public int getBlockSize() {
return blockSize;
}
public void setBlockSize(int blockSize) {
this.blockSize = blockSize;
}
}
package kr.or.ddit.util;
import java.util.List;
// 페이징 관련 정보 + 게시글 정보
// new ArticlePage<FreeBoardVO>(total, currentPage, size, content);
public class MiniPage<T> {
// 전체글 수
private int total;
// 현재 페이지 번호
private int currentPage;
// 전체 페이지수
private int totalPages;
// 블록의 시작 페이지 번호
private int startPage;
// 블록의 종료 페이지 번호
private int endPage;
//검색어
private String keyword = "";
//요청URL
private String url = "";;
//select 결과 데이터
private List<T> content;
// 페이징 처리
private String pagingArea = "";
// 블록크기
private int blockSize = 3;
// 공통 코드[검색조건]
private String comCode;
// 공통 코드 상세 명[검색조건]
private String comCodeDetNm;
// 생성자(Constructor) : 페이징 정보를 생성
// 753 1 10 select결과 =>10행 , comCode , comCodeDetNm
public MiniPage(int total, int currentPage, int size, List<T> content, String comCode , String comCodeDetNm) {
//size : 한 화면에 보여질 목록의 행 수
this.total = total;//753
this.currentPage = currentPage;//1
this.content = content;
// 매개변수를 property에 세팅↓↓
this.comCode = comCode;
this.comCodeDetNm = comCodeDetNm;
//전체글 수가 0이면?
if(total == 0) {
totalPages = 0;//전체 페이지 수
startPage = 0;//블록 시작번호
endPage = 0; //블록 종료번호
} else {//글이 있다면
//전체 페이지 수 = 전체글 수 / 한 화면에 보여질 목록의 행 수
//3 = 31 / 10
totalPages = total / size;//75
//나머지가 있다면, 페이지를 1 증가
if(total % size > 0) {//나머지3
totalPages++;//76
}
// 페이지 블록 시작번호를 구하는 공식
// 블록시작번호 = 현재페이지 / 페이지크기 * 페이지크기 + 1
startPage = currentPage / blockSize * blockSize + 1;//1
//현재페이지 % 페이지크기 => 0일 때 보정
if(currentPage % blockSize == 0) {
startPage -= blockSize;
}
//블록종료번호 = 시작페이지번호 + (페이지크기 - 1)
//[1][2][3][4][5][다음]
endPage = startPage + (blockSize - 1);//5
//종료페이지번호 > 전체페이지수
if(endPage > totalPages) {
endPage = totalPages;
}
}
pagingArea += "<div class='col-sm-12 col-md-7'>";
pagingArea += "<div class='dataTables_paginate paging_simple_numbers' id='example2_paginate'>";
pagingArea += "<ul class='pagination'>";
pagingArea += "<li class='paginate_button page-item previous ";
if(this.startPage < 4) {
//
pagingArea += "disabled";
}
pagingArea += "'";
pagingArea += " id='example2_previous'>";
pagingArea += "<a href='"+this.url+"?currentPage="+(this.startPage-blockSize)+"&comCode="+this.comCode+"&comCodeDetNm="+this.comCodeDetNm+"' aria-controls='example2' data-dt-idx='0' tabindex='0'";
// startPage에서 blockSize만큼 뺀다
pagingArea += "class='page-link'>Previous</a></li>";
for(int pNo=this.startPage;pNo<=this.endPage;pNo++) {
pagingArea += "<li class='paginate_button page-item ";
if(this.currentPage == pNo) {
pagingArea += "active";
}
pagingArea += "'>";
pagingArea += "<a href='"+this.url+"?currentPage="+pNo+"&comCode="+this.comCode+"&comCodeDetNm="+this.comCodeDetNm+"' aria-controls='example2' data-dt-idx='1' tabindex='0'";
pagingArea += "class='page-link'>"+pNo+"</a>";
pagingArea += "</li>";
}
pagingArea += "<li class='paginate_button page-item next ";
if(this.endPage>=this.totalPages) {
pagingArea += "disabled";
}
pagingArea += "' id='example2_next'><a ";
pagingArea += "href='"+this.url+"?currentPage="+(this.startPage+blockSize)+"&comCode="+this.comCode+"&comCodeDetNm="+this.comCodeDetNm+"' aria-controls='example2' data-dt-idx='7' ";
// 블록사이즈를 더해주면 다음 블록으로 이동
pagingArea += "tabindex='0' class='page-link'>Next</a></li>";
pagingArea += "</ul>";
pagingArea += "</div>";
pagingArea += "</div>";
}//end 생성자
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
public int getCurrentPage() {
return currentPage;
}
public void setCurrentPage(int currentPage) {
this.currentPage = currentPage;
}
public int getTotalPages() {
return totalPages;
}
public void setTotalPages(int totalPages) {
this.totalPages = totalPages;
}
public int getStartPage() {
return startPage;
}
public void setStartPage(int startPage) {
this.startPage = startPage;
}
public int getEndPage() {
return endPage;
}
public void setEndPage(int endPage) {
this.endPage = endPage;
}
public String getKeyword() {
return keyword;
}
public void setKeyword(String keyword) {
this.keyword = keyword;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public List<T> getContent() {
return content;
}
public void setContent(List<T> content) {
this.content = content;
}
//전체 글의 수가 0인가?
public boolean hasNoArticles() {
return this.total == 0;
}
//데이터가 있나?
public boolean hasArticles() {
return this.total > 0;
}
//페이징 블록을 자동화
public String getPagingArea() {
return this.pagingArea;
}
public void setPagingArea(String pagingArea) {
this.pagingArea = pagingArea;
}
public int getBlockSize() {
return blockSize;
}
public void setBlockSize(int blockSize) {
this.blockSize = blockSize;
}
}
comCodeList메소드 수정 , 검색조건 추가
package kr.or.ddit.comCode.controller;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import kr.or.ddit.comCode.service.ComCodeService;
import kr.or.ddit.comCode.vo.ComCodeDetVO;
import kr.or.ddit.comCode.vo.ComCodeVO;
import kr.or.ddit.util.MiniPage;
import lombok.extern.slf4j.Slf4j;
@RequestMapping("/comCode")
@Controller
@Slf4j
public class ComCodeController {
@Autowired
ComCodeService comCodeService;
// 공통코드 정보 미리 만들어놓기 comCode로 시작하는 모든 요청에 대해 자동으로 생성된다!
@ModelAttribute
public void comCode(Model model) {
// 공통 코드 목록 new HashMap -> 검색을 하는게 아니기 때문에 아무것도 없는 HashMap을 넣는다
List<ComCodeVO> comCodeVOList = this.comCodeService.comCodeList(new HashMap<String, Object>());
log.info("comCodeVOList : " + comCodeVOList);
model.addAttribute("data" , comCodeVOList);
}
//공통 코드 목록
/*
요청URI : /comCode/comCodeList?comCode=A07&comCodeDetNm=교부¤tPage=3
요청파라미터 : comCode=A07&comCodeDetNm=교부
요청방식 : get
*/
@GetMapping("/comCodeList")
public String comCodeList(Model model,
@RequestParam(value = "comCode" , required = false ,defaultValue = "" ) String comCode,
@RequestParam(value = "comCodeDetNm" , required = false , defaultValue = "") String comCodeDetNm,
@RequestParam(value = "currentPage" , required = false , defaultValue = "1") int currentPage) {
log.info("comCodeList -> comCode : " + comCode);
log.info("comCodeList -> comCodeDetNm : " + comCodeDetNm);
Map<String , Object> comCodeMap = new HashMap<String, Object>();
comCodeMap.put("currentPage" , currentPage);
// 공통 코드 목록, 페이징처리 -> comCodeVOList에 currentPage를 던져줘야 한다 comCodeMap{"currentPage":"1"}
List<ComCodeVO> comCodeVOList = this.comCodeService.comCodeList(comCodeMap);
log.info("comCodeVOList : " + comCodeVOList);
// 공통 코드 목록 전체 행 수
int total = this.comCodeService.comCodeTotal();
log.info("comCodeList -> total : " + total);
// 공통 코드 상세 목록
Map<String , Object> map = new HashMap<String, Object>();
map.put("comCode", comCode);
map.put("comCodeDetNm" , comCodeDetNm);
List<ComCodeDetVO> comCodeDetVOList = this.comCodeService.comCodeDetVOList(map);
// 공통 코드 목록에 대한 페이징 처리
// comCode/comCodeList?comCode=A07&comCodeDetNm=교부¤tPage=3
MiniPage<ComCodeVO> miniPage
= new MiniPage<ComCodeVO>(total, currentPage, 5, comCodeVOList, comCode , comCodeDetNm);
model.addAttribute("miniPage" , miniPage);
// model.addAttribute("comCodeVOList" , comCodeVOList);
model.addAttribute("comCodeDetVOList" , comCodeDetVOList);
// forwarding : jsp
return "admin/comCodeList";
}
}
페이징 처리 준비(db작업)
select com_code , com_code_nm
from com_code
order by 1;
//order by 1 => 순서
↓↓↓↓↓↓↓↓↓↓ 아래와 같이 수정
select T.*
from(
select row_number() over(order by com_code) rnum , com_code , com_code_nm
from com_code
) T
where T.rnum between 11 and 15;
페이징 테스
comCode_SQL 수정
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="kr.or.ddit.comCode.mapper.ComCodeMapper">
<!-- COM_CODE 목록
comCodeMap{"currentPage":"1"}
-->
<select id="comCodeList" parameterType="hashMap" resultType="comCodeVO">
SELECT T.*
FROM
(
SELECT ROW_NUMBER() OVER(ORDER BY COM_CODE) RNUM
, COM_CODE, COM_CODE_NM
FROM COM_CODE
) T
<if test="currentPage!=null and currentPage!=''">
WHERE T.RNUM BETWEEN (#{currentPage} * 5) - (5 - 1) AND (#{currentPage} * 5)
</if>
</select>
<select id="comCodeDetVOList" parameterType="hashMap" resultType="comCodeDetVO">
SELECT COM_CODE_DET, COM_CODE_DET_NM, COM_CODE
FROM COM_CODE_DET
WHERE 1 = 1
<if test="comCode!=null and comCode!=''">
AND COM_CODE = #{comCode}
</if>
<if test="comCodeDetNm!=null and comCodeDetNm!=''">
AND COM_CODE_DET_NM LIKE '%' || #{comCodeDetNm} || '%'
</if>
</select>
<!-- 공통 코드 목록 전체 행 수 -->
<select id="comCodeTotal" resultType="int">
SELECT COUNT(*) FROM COM_CODE
WHERE 1 = 1
</select>
</mapper>
서버 재기동 후 페이징 적용 확인
(ComCodeService 인터페이스 , 구현클래스 , ComCodeMapper 인터페이스 체크 , ComCodeVO rnum 멤버변수 추가)
comCodeList.jsp 변수명 체크
<div class='jsgrid-pager-container text-center'>
<div class='jsgrid-pager'>
<span class='jsgrid-pager-nav-button jsgrid-pager-nav-inactive-button'>
<a href=''>Prev</a>
</span>
<span class='jsgrid-pager-page'><a href=''>2</a></span>
<span class='jsgrid-pager-nav-button'><a href=''>Next</a></span>
</div>
</div>
MiniPage 수정
package kr.or.ddit.util;
import java.util.List;
//페이징 관련 정보 + 게시글 정보
// new ArticlePage<FreeBoardVO>(total, currentPage, size, content);
public class MiniPage<T> {
//전체글 수
private int total;
// 현재 페이지 번호
private int currentPage;
// 전체 페이지수
private int totalPages;
// 블록의 시작 페이지 번호
private int startPage;
//블록의 종료 페이지 번호
private int endPage;
//검색어
private String keyword = "";
//요청URL
private String url = "";
//select 결과 데이터
private List<T> content;
//페이징 처리
private String pagingArea = "";
//블록 크기
private int blockSize = 3;
//공통 코드[검색조건]
private String comCode;
//공통 코드 상세 명[검색조건]
private String comCodeDetNm;
//생성자(Constructor) : 페이징 정보를 생성
// 753 1 10 select결과10행, comCode, comCodeDetNm
public MiniPage(int total, int currentPage, int size, List<T> content, String comCode, String comCodeDetNm) {
//size : 한 화면에 보여질 목록의 행 수
this.total = total;//753
this.currentPage = currentPage;//1
this.content = content;
this.comCode = comCode;
this.comCodeDetNm = comCodeDetNm;
//전체글 수가 0이면?
if(total==0) {
totalPages = 0;//전체 페이지 수
startPage = 0;//블록 시작번호
endPage = 0; //블록 종료번호
}else {//글이 있다면
//전체 페이지 수 = 전체글 수 / 한 화면에 보여질 목록의 행 수
//3 = 31 / 10
totalPages = total / size;//75
//나머지가 있다면, 페이지를 1 증가
if(total % size > 0) {//나머지3
totalPages++;//76
}
//페이지 블록 시작번호를 구하는 공식
// 블록시작번호 = 현재페이지 / 페이지크기 * 페이지크기 + 1
startPage = currentPage / blockSize * blockSize + 1;//1
//현재페이지 % 페이지크기 => 0일 때 보정
if(currentPage % blockSize == 0) {
startPage -= blockSize;
}
//블록종료번호 = 시작페이지번호 + (페이지크기 - 1)
//[1][2][3][다음]
endPage = startPage + (blockSize - 1);//5
//종료페이지번호 > 전체페이지수
if(endPage > totalPages) {
endPage = totalPages;
}
}
// pagingArea += "<div class='col-sm-12 col-md-7'>";
// pagingArea += "<div class='dataTables_paginate paging_simple_numbers' id='example2_paginate'>";
// pagingArea += "<ul class='pagination'>";
// pagingArea += "<li class='paginate_button page-item previous ";
// if(this.startPage<4) {
// pagingArea += "disabled ";
// }
// pagingArea += "'";
// pagingArea += "id='example2_previous'>";
// pagingArea += "<a href='"+this.url+"?currentPage="+(this.startPage-blockSize)+"&comCode="+this.comCode+"&comCodeDetNm="+this.comCodeDetNm+"' aria-controls='example2' data-dt-idx='0' tabindex='0' ";
// pagingArea += "class='page-link'>Previous</a></li>";
//
// for(int pNo=this.startPage;pNo<=this.endPage;pNo++) {
// pagingArea += "<li class='paginate_button page-item ";
// if(this.currentPage == pNo) {
// pagingArea += "active";
// }
// pagingArea += "'>";
// pagingArea += "<a href='"+this.url+"?currentPage="+pNo+"&comCode="+this.comCode+"&comCodeDetNm="+this.comCodeDetNm+"' aria-controls='example2' data-dt-idx='1' tabindex='0' ";
// pagingArea += "class='page-link'>"+pNo+"</a>";
// pagingArea += "</li>";
// }
// pagingArea += "<li class='paginate_button page-item next ";
// if(this.endPage>=this.totalPages) {
// pagingArea += "disabled";
// }
// pagingArea += "' id='example2_next'><a ";
// pagingArea += "href='"+this.url+"?currentPage="+(this.startPage+blockSize)+"&comCode="+this.comCode+"&comCodeDetNm="+this.comCodeDetNm+"' aria-controls='example2' data-dt-idx='7' ";
// pagingArea += "tabindex='0' class='page-link'>Next</a></li>";
// pagingArea += "</ul>";
// pagingArea += "</div>";
// pagingArea += "</div>";
pagingArea += "<div class='jsgrid-pager-container text-center'>";
pagingArea += "<div class='jsgrid-pager'>";
pagingArea += "<span class='jsgrid-pager-nav-button jsgrid-pager-nav-";
if(this.startPage<4) {
pagingArea += "inactive-";
}
pagingArea += "button'>";
pagingArea += "<a href='"+this.url+"?currentPage="+(this.startPage-blockSize)+"&comCode="+this.comCode+"&comCodeDetNm="+this.comCodeDetNm+"'>Prev</a>";
pagingArea += "</span>";
for(int pNo=this.startPage;pNo<=this.endPage;pNo++) {
pagingArea += "<span class='jsgrid-pager-page'><a href='"+this.url+"?currentPage="+pNo+"&comCode="+this.comCode+"&comCodeDetNm="+this.comCodeDetNm+"'>"+pNo+"</a></span>";
}
pagingArea += "<span class='jsgrid-pager-nav-";
if(this.endPage>=this.totalPages) {
pagingArea += "inactive-";
}
pagingArea += "button'>";
pagingArea += "<a href='"+this.url+"?currentPage="+(this.startPage+blockSize)+"&comCode="+this.comCode+"&comCodeDetNm="+this.comCodeDetNm+"'>Next</a>";
pagingArea += "</span>";
pagingArea += "</div>";
pagingArea += "</div>";
}//end 생성자
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
public int getCurrentPage() {
return currentPage;
}
public void setCurrentPage(int currentPage) {
this.currentPage = currentPage;
}
public int getTotalPages() {
return totalPages;
}
public void setTotalPages(int totalPages) {
this.totalPages = totalPages;
}
public int getStartPage() {
return startPage;
}
public void setStartPage(int startPage) {
this.startPage = startPage;
}
public int getEndPage() {
return endPage;
}
public void setEndPage(int endPage) {
this.endPage = endPage;
}
public String getKeyword() {
return keyword;
}
public void setKeyword(String keyword) {
this.keyword = keyword;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public List<T> getContent() {
return content;
}
public void setContent(List<T> content) {
this.content = content;
}
//전체 글의 수가 0인가?
public boolean hasNoArticles() {
return this.total == 0;
}
//데이터가 있나?
public boolean hasArticles() {
return this.total > 0;
}
public void setPagingArea(String pagingArea) {
this.pagingArea = pagingArea;
}
//페이징 블록을 자동화
public String getPagingArea() {
return this.pagingArea;
}
public int getBlockSize() {
return blockSize;
}
public void setBlockSize(int blockSize) {
this.blockSize = blockSize;
}
}
eclipse palette 검색후 설치(이클립스 색상 추출기)
공통코드 선택시 선택한 공통코드에 배경색 추가 (선택한 공통 코드와 목록에 존재하는 공통 코드가 같으면 배경색 추가)
<c:forEach var="comCodeVO" items="${miniPage.content}" varStatus="stat">
<tr
<c:if test="${param.comCode==comCodeVO.comCode}"> style="background-color: #49BEFF;"</c:if>
>
<th scope="row"><a href="/comCode/comCodeList?comCode=${comCodeVO.comCode}¤tPage=${param.currentPage}">${comCodeVO.comCode}</a></th>
<td>${comCodeVO.comCodeNm}</td>
</tr>
</c:forEach>
특정 공통코드 선택시 해당 코드 배경색 추가 확인
비동기 처리(Ajax)로 해보기
관계자버튼 추가한 뒤 확인
관계자 테이블 데이터 삽입(우선 코멘트 추가)
// 위처럼 직접 입력 혹은 아래 쿼리문으로 코멘트 삽입
COMMENT ON COLUMN OFC.OFC_NO IS '관계자 번호';
COMMENT ON COLUMN OFC.EXP_START_DATE IS '유효 시작 일자';
COMMENT ON COLUMN OFC.EXP_END_DATE IS '유효 종료 일자';
COMMENT ON COLUMN OFC.OFC_NM IS '관계자 명';
COMMENT ON COLUMN OFC.OFC_IDNTFC_NO IS '관계자 식별 번호';
COMMENT ON COLUMN OFC.IHIDNUM IS '주민등록번호';
COMMENT ON COLUMN OFC.FRGNRIDNTFCNO IS '외국인식별번호';
COMMENT ON COLUMN OFC.BSNM_REGIST_NO IS '사업자 등록 번호';
COMMENT ON COLUMN OFC.OFC_SE IS '관계자 구분';
위 컬럼에서 관계자 식별 번호?
주민번호로 할지 외국인 식별 번호로 할지 선택
ex) 관계자 식별번호가 1 -> 주민번호 , 2-> 외국인 식별번호
임시데이터 추가
ofc 패키지 , 하위패키지 생성
OfcContoller 생성 후 메소드 작성
package kr.or.ddit.ofc.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@RequestMapping("/ofc")
@Controller
public class OfcController {
// 관계자 관계(/ofc/ofcRltiMapping) , 속성이 하나인 경우에는 value 생략 가능
@GetMapping("/ofcRltiMapping")
public String ofcRltiMapping() {
//forwarding : jsp
return "admin/ofcRltiMapping";
}
// 신고 오류 누적(/sttemntErrAccmltList)
// 관계자 연락처(/ofcCttpcList)
// 관계자 구분(/ofcSeList)
//
}
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<div class="row">
<div class="card-group">
<div class="card">
<img src="..." class="card-img-top" alt="...">
<div class="card-body">
<h5 class="card-title">Card title</h5>
<p class="card-text">This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.</p>
<p class="card-text"><small class="text-body-secondary">Last updated 3 mins ago</small></p>
</div>
</div>
<div class="card">
<img src="..." class="card-img-top" alt="...">
<div class="card-body">
<h5 class="card-title">Card title</h5>
<p class="card-text">This card has supporting text below as a natural lead-in to additional content.</p>
<p class="card-text"><small class="text-body-secondary">Last updated 3 mins ago</small></p>
</div>
</div>
<div class="card">
<img src="..." class="card-img-top" alt="...">
<div class="card-body">
<h5 class="card-title">Card title</h5>
<p class="card-text">This is a wider card with supporting text below as a natural lead-in to additional content. This card has even longer content than the first to show that equal height action.</p>
<p class="card-text"><small class="text-body-secondary">Last updated 3 mins ago</small></p>
</div>
</div>
</div>
</div>
img 태그부분 아래 div태그로 변경
<div class="card-header bg-transparent border-success">Header</div>
변경 후
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<div class="row">
<div class="card-group">
<div class="card border-success mb-3">
<div class="card-header bg-transparent border-success">관계 주체</div>
<div class="card-body text-secondary">
<h5 class="card-title">Card title</h5>
<p class="card-text">This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.</p>
<p class="card-text"><small class="text-body-secondary">Last updated 3 mins ago</small></p>
</div>
</div>
<div class="card border-success mb-3">
<div class="card-header bg-transparent border-success">매핑 완료</div>
<div class="card-body text-secondary">
<h5 class="card-title text-secondary">Card title</h5>
<p class="card-text text-secondary">This card has supporting text below as a natural lead-in to additional content.</p>
<p class="card-text"><small class="text-body-secondary">Last updated 3 mins ago</small></p>
</div>
</div>
<div class="card border-success mb-3">
<div class="card-header bg-transparent border-success">관계 대상</div>
<div class="card-body text-secondary">
<h5 class="card-title">Card title</h5>
<p class="card-text">This is a wider card with supporting text below as a natural lead-in to additional content. This card has even longer content than the first to show that equal height action.</p>
<p class="card-text"><small class="text-body-secondary">Last updated 3 mins ago</small></p>
</div>
</div>
</div>
</div>
아랫부분에 라디오 버튼 추가하기
<div class="row">
<div class="card">
<div class="card-header">
관계자 관계 구분
</div>
<div class="card-body">
<div class="form-check" style="float:left;">
<input class="form-check-input" type="radio" name="flexRadioDefault" id="flexRadioDefault1">
<label class="form-check-label" for="flexRadioDefault1">
Default radio
</label>
</div>
<div class="form-check" style="float:left;">
<input class="form-check-input" type="radio" name="flexRadioDefault" id="flexRadioDefault1">
<label class="form-check-label" for="flexRadioDefault1">
Default radio
</label>
</div>
<div class="form-check" style="float:left;">
<input class="form-check-input" type="radio" name="flexRadioDefault" id="flexRadioDefault1">
<label class="form-check-label" for="flexRadioDefault1">
Default radio
</label>
</div>
</div>
</div>
</div>
페이지 확인
유효기간 추가 , 페이지 확인
card-tile 내용 지운뒤 정보 가져오기
<script type="text/javascript">
$(function () {
// 매핑 실행 버튼
$("#btnMapping").on("click" , function () {
console.log("매핑테스트");
if(!$("input[name='rltiMbyOfcNo']").is(":checked")){// 체크시 : true -> ! -> false
// 체크가 되지 않았다면
var Toast = Swal.mixin({
toast:true,
position:'top-end',
showConfirmButton:false,
timer : 3000
});
Toast.fire({
icon:'error',
title:'관계 주체를 선택해주세요'
});
$("input[name='rltiMbyOfcNo']").focus();
return;
}
if(!$("input[name='rltiTrgetOfcNo']").is(":checked")){// 체크시 : true -> ! -> false
// 체크가 되지 않았다면
var Toast = Swal.mixin({
toast:true,
position:'top-end',
showConfirmButton:false,
timer : 3000
});
Toast.fire({
icon:'error',
title:'관계 대상을 선택해주세요'
});
$("input[name='rltiTrgetOfcNo']").focus();
return;
}
if(!$("input[name='ofcRltiSe']").is(":checked")){// 체크시 : true -> ! -> false
// 체크가 되지 않았다면
var Toast = Swal.mixin({
toast:true,
position:'top-end',
showConfirmButton:false,
timer : 3000
});
Toast.fire({
icon:'error',
title:'관계 구분을 선택해주세요'
});
$("input[name='ofcRltiSe']").focus();
return;
}
// 관계 주체 : input의 name값이 rltiMbyOfcNo인 값을 찾는다(5개 배열!)
let rltiMbyOfcNo = $("input[name='rltiMbyOfcNo']:checked").val();
console.log("rltiMbyOfcNo : " + rltiMbyOfcNo);
// 관계 대상 5개 라디오 배열
let rltiTrgetOfcVO = $("input[name='rltiTrgetOfcNo']:checked").val();
console.log("rltiTrgetOfcNo : " + rltiTrgetOfcVO);
// 관계 구분 : 3개 라디오 배열
let ofcRltiSe = $("input[name='ofcRltiSe']:checked").val();
console.log("ofcRltiSe : " + ofcRltiSe);
// 유효기간 시작날짜
let expStartDate = $("#expStartDate").val();
console.log("expStartDate : " + expStartDate)
// 유효기간 종료날짜
let expEndDate = $("#expEndDate").val();
console.log("expEndDate : " + expEndDate);
// json객체 생성
let data = {
"rltiMbyOfcNo":rltiMbyOfcNo,
"rltiTrgetOfcVO":rltiTrgetOfcVO,
"ofcRltiSe":ofcRltiSe,
"expStartDate":expStartDate,
"expEndDate":expEndDate
};
console.log("data : " , data);
// insert 처리
});
// 관계 주체 목록
$.ajax({
url : "/ofc/ofcList" ,
type : "post",
beforeSend:function(xhr){
xhr.setRequestHeader("${_csrf.headerName}","${_csrf.token}");
},
success:function(result){
console.log("result : " , result);
//관계 주체 테이블
let str = "";
str += "<table class='table'>";
str += "<thead>";
str += "<tr>";
str += "<th scope='col'>선택</th>";
str += "<th scope='col'>관계자번호</th>";
str += "<th scope='col'>관계자명</th>";
str += "</tr>";
str += "</thead>";
str += "<tbody>";
// result : List<OfcVO> , 반복구간 시작
$.each(result , function(idx , ofcVO){
// label -> ofcNo
str += "<tr>";
str += "<th><input class='form-check-input clsMby' type='radio' name='rltiMbyOfcNo' value='"+ofcVO.ofcNo+"' id='rltiMbyOfcNo"+(idx+1)+"'></th>";
str += "<th scope='row'><label class='form-check-label' for='rltiMbyOfcNo"+(idx+1)+"'>"+ofcVO.ofcNo+"</label></th>";
str += "<td>"+ofcVO.ofcNm+"</td>";
str += "</tr>";
}); // 반복구간 끝
str += "</tbody>";
str += "</table>";
$("#divMby").html(str);
//관계 대상 테이블
str = "";
str += "<table class='table'>";
str += "<thead>";
str += "<tr>";
str += "<th scope='col'>선택</th>";
str += "<th scope='col'>관계자번호</th>";
str += "<th scope='col'>관계자명</th>";
str += "</tr>";
str += "</thead>";
str += "<tbody>";
// result : List<OfcVO> , 반복구간 시작
$.each(result , function(idx , ofcVO){
// label -> ofcNo
str += "<tr>";
str += "<th><input class='form-check-input clsTrget' type='radio' name='rltiTrgetOfcNo' value='"+ofcVO.ofcNo+"' id='rltiTrgetOfcNo"+(idx+1)+"'></th>";
str += "<th scope='row'><label class='form-check-label' for='rltiTrgetOfcNo"+(idx+1)+"'>"+ofcVO.ofcNo+"</label></th>";
str += "<td>"+ofcVO.ofcNm+"</td>";
str += "</tr>";
}); // 반복구간 끝
str += "</tbody>";
str += "</table>";
$("#divTrget").html(str);
}
})
});
</script>
데이터 삽입
INSERT INTO OFC_RLTI(RLTI_MBY_OFC_NO, RLTI_TRGET_OFC_NO, EXP_START_DATE, EXP_END_DATE, OFC_RLTI_SE)
VALUES('2024001','2024002','2024-02-21','2024-02-29','조직');
MERGE INTO OFC_RLTI A
USING DUAL ON(RLTI_MBY_OFC_NO = '2024001' AND RLTI_TRGET_OFC_NO='2024002'
AND EXP_START_DATE='2024-02-21' AND EXP_END_DATE='2024-02-29')
WHEN MATCHED THEN
UPDATE
SET A.OFC_RLTI_SE = '개인'
WHERE A.RLTI_MBY_OFC_NO = '2024001' AND A.RLTI_TRGET_OFC_NO='2024002'
AND A.EXP_START_DATE='2024-02-21' AND A.EXP_END_DATE='2024-02-29'
WHEN NOT MATCHED THEN
INSERT (RLTI_MBY_OFC_NO, RLTI_TRGET_OFC_NO, EXP_START_DATE, EXP_END_DATE, OFC_RLTI_SE)
VALUES('2024001','2024002','2024-02-21','2024-02-29','조직'