romworld

Spring 19 - EMP 테이블 (직원) 등록, 상세보기 , 수정,삭제,목록, 검색Toast, Merge_Into 본문

Spring

Spring 19 - EMP 테이블 (직원) 등록, 상세보기 , 수정,삭제,목록, 검색Toast, Merge_Into

inderrom 2023. 2. 7. 17:48

EMP(직원) 테이블 컬럼 수정

  • 관리번호(매니저)

 

<aside.jsp>

  • 고객관리 밑에 직원관리 카데고리를 만들어준다.
<!-- 직원관리 -->
    <li class="nav-item">
        <a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapseEmp"
            aria-expanded="true" aria-controls="collapseEmp">
            <i class="fas fa-fw fa-check"></i>
            <span>직원관리</span>
        </a>
        <div id="collapseEmp" class="collapse" aria-labelledby="headingUtilities"
            data-parent="#accordionSidebar">
            <div class="bg-white py-2 collapse-inner rounded">
                <h6 class="collapse-header">직원정보관리:</h6>
                <a class="collapse-item" href="/emp/create">직원등록</a>
                <a class="collapse-item" href="/emp/list">직원목록</a>
            </div>
        </div>
    </li>

 


 

<EmpVO.java>

  • private String empMjNum;
  • emppay는 @NotNull
package kr.or.ddit.vo;

import java.util.List;

import javax.validation.constraints.NotNull;

import org.hibernate.validator.constraints.NotBlank;

import lombok.Data;

//직원
@Data
public class EmpVO {
	//직원 번호
	@NotBlank
	private String empNum;
	//주소
	private String empAddr;
	//연락처
	@NotBlank
	private String empPne;
	//직원 명
	@NotBlank
	private String empNm;
	//급여
	@NotNull
	private int empPay;
	//매니저
	private String empMjNum;
	//직원(EMP) : 서비스(SER) = 1 : N
	private List<SerVO> serVOList;

}

 

<EmpController.java>

package kr.or.ddit.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;

import kr.or.ddit.vo.EmpVO;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Controller
@RequestMapping("/emp")
public class EmpController {
	// 요청 URI : /emp/create
	// 요청방식 : get
	
	@GetMapping("/create")
	public String create(@ModelAttribute("empVO") EmpVO empVO) {
		//forwarding
		return "emp/create";
		
	}
}

 

<create.jsp>

부트스트랩 적용해서 create 꾸며주자

https://getbootstrap.com/docs/5.3/forms/layout/

 

Layout

Give your forms some structure—from inline to horizontal to custom grid implementations—with our form layout options.

getbootstrap.com

 

<form class="row g-3">
  <div class="col-md-6">
    <label for="inputEmail4" class="form-label">Email</label>
    <input type="email" class="form-control" id="inputEmail4">
  </div>
  <div class="col-md-6">
    <label for="inputPassword4" class="form-label">Password</label>
    <input type="password" class="form-control" id="inputPassword4">
  </div>
  <div class="col-12">
    <label for="inputAddress" class="form-label">Address</label>
    <input type="text" class="form-control" id="inputAddress" placeholder="1234 Main St">
  </div>
  <div class="col-12">
    <label for="inputAddress2" class="form-label">Address 2</label>
    <input type="text" class="form-control" id="inputAddress2" placeholder="Apartment, studio, or floor">
  </div>
  <div class="col-md-6">
    <label for="inputCity" class="form-label">City</label>
    <input type="text" class="form-control" id="inputCity">
  </div>
  <div class="col-md-4">
    <label for="inputState" class="form-label">State</label>
    <select id="inputState" class="form-select">
      <option selected>Choose...</option>
      <option>...</option>
    </select>
  </div>
  <div class="col-md-2">
    <label for="inputZip" class="form-label">Zip</label>
    <input type="text" class="form-control" id="inputZip">
  </div>
  <div class="col-12">
    <div class="form-check">
      <input class="form-check-input" type="checkbox" id="gridCheck">
      <label class="form-check-label" for="gridCheck">
        Check me out
      </label>
    </div>
  </div>
  <div class="col-12">
    <button type="submit" class="btn btn-primary">Sign in</button>
  </div>
</form>

 

<%@ page language="java" contentType="text/html;charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<link rel="stylesheet" href="/resources/css/bootstrap.min.css" />
<script src="https://ssl.daumcdn.net/dmaps/map_js_init/postcode.v2.js"></script>
<script type="text/javascript" src="/resources/js/jquery-3.6.0.js"></script>
<script type="text/javascript">
$(function(){
	//다음 우편번호 검색
	$("#btnPostno").on("click",function(){
		new daum.Postcode({
			//다음 창에서 검색이 완료되면 콜백함수에 의해 결과 데이터가 data 객체로 들어옴
			oncomplete:function(data){
				//우편번호
				$("#zipCode").val(data.zonecode);
				$("#address").val(data.address);
				$("#detAddress").val(data.buildingName);
			}
		}).open();
	});
});
</script>
<form:form modelAttribute="empVO" action="/emp/createPost" method="post"
		 class="row g-3">
	<!-- 직원번호 시작 -->
	<div class="col-md-6" style="clear:both;">
	  <label for="empNum" class="form-label">직원번호</label>
	  <input type="text" name="empNum" class="form-control" id="empNum"
	  	placeholder="직원번호를 입력해주세요" />
	</div>
	<!-- 직원번호 끝 -->
	<!-- 주소 시작 -->
	<div class="col-md-2">
    	<label for="zipCode" class="form-label">우편번호</label>
    	<input type="text" name="zipCode" class="form-control" id="zipCode"
    		placeholder="우편번호를 검색해주세요" />
    	<button type="button" class="btn btn-primary" id="btnPostno">검색</button>
	</div>
	<div class="col-12">
	    <label for="address" class="form-label">주소</label>
	    <input type="text" name="address" class="form-control" id="address" 
	    	placeholder="주소를 검색해주세요">
	</div>
	<div class="col-12">
	    <label for="detAddress" class="form-label">상세주소</label>
	    <input type="text" name="detAddress" class="form-control" id="detAddress" 
	    	placeholder="상세주소를 입력해주세요">
	</div>
    <!-- 주소 끝 -->
    <!-- 연락처 시작 -->
	<div class="col-md-6">
	  <label for="empPne" class="form-label">연락처</label>
	  <input type="text" name="empPne" class="form-control" id="empPne"
	  	placeholder="연락처를 입력해주세요" />
	</div>
	<!-- 연락처 끝 -->
    <!-- 직원명 시작 -->
	<div class="col-md-6">
	  <label for="empNm" class="form-label">직원명</label>
	  <input type="text" name="empNm" class="form-control" id="empNm"
	  	placeholder="직원명을 입력해주세요" />
	</div>
	<!-- 직원명 끝 -->
    <!-- 급여 시작 -->
	<div class="col-md-6">
	  <label for="empPay" class="form-label">급여</label>
	  <input type="number" name="empPay" class="form-control" id="empPay"
	  	placeholder="급여를 입력해주세요" />
	</div>
	<!-- 급여 끝 -->
	<div class="col-12">
	  <button type="submit" class="btn btn-primary">Sign in</button>
	</div>
</form:form>

 


직원번호 자동생성, 등록

 

쿼리문

SELECT NVL(SUBSTR(MAX(EMP_NUM),1,3),'EMP')
     || TRIM(TO_CHAR(NVL(SUBSTR(MAX(EMP_NUM),4),0) + 1,'000'))
FROM   EMP;

 

<EmpMapper.java>

package kr.or.ddit.mapper;

import kr.or.ddit.vo.EmpVO;

public interface EmpMapper {
	
	// 다음 직원번호를 가져옴
	public String getEmpNum();

}

 

<emp.SQL.xml>

<?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">
  <!-- namespace : xml 파일이 여러개일 수 있으므로
  		이를 구별하기 위한 식별 용도로 사용 -->
  <mapper namespace="kr.or.ddit.mapper.EmpMapper">
	<!-- 직원테이블(EMP)의 기본키 데이터 생성 -->
	<select id="getEmpNum" resultType="String">
		SELECT NVL(SUBSTR(MAX(EMP_NUM),1,3),'EMP')
    		 || TRIM(TO_CHAR(NVL(SUBSTR(MAX(EMP_NUM),4),0)+1,'000'))
		FROM   EMP
	</select>

  </mapper>

<EmpService.java>

package kr.or.ddit.service;

import kr.or.ddit.vo.EmpVO;

public interface EmpService {
	
	// 직원테이블(EMP) 직원번호 자동생성
	public String getEmpNum();

}

 

<EmpServiceImple.java>

package kr.or.ddit.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import kr.or.ddit.mapper.EmpMapper;
import kr.or.ddit.service.EmpService;
import kr.or.ddit.vo.EmpVO;

@Service
public class EmpServiceImpl implements EmpService {
	@Autowired
	EmpMapper empMapper;
	
	// 직원테이블(EMP)의 기본키 데이터 생성
	@Override
	public String getEmpNum() {
		return this.empMapper.getEmpNum();
	}
	
}

 

<EmpController.java>

package kr.or.ddit.controller;

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 kr.or.ddit.service.EmpService;
import kr.or.ddit.vo.EmpVO;

@RequestMapping("/emp")
@Controller
public class EmpController {
	@Autowired
	EmpService empService;
	
	//요청URI : /emp/create
	//요청방식 : get
	@GetMapping("/create")
	public String create(@ModelAttribute("empVO") EmpVO empVO
			, Model model) {
		
		//다음 직원번호를 가져옴
		//서비스의 메서드 호출
		String empNum = this.empService.getEmpNum();
		//1. <form:form modelAttribute="empVO"
		empVO.setEmpNum(empNum);
		//2. ${empNum} 를 사용하는 경우
		model.addAttribute("empNum", empNum);		
		
		//forwarding
		return "emp/create";
	}
}

 

<create.jsp>

  • ajax 사용해서 신규 직원번호 가져와보기
<%@ page language="java" contentType="text/html;charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<link rel="stylesheet" href="/resources/css/bootstrap.min.css" />
<script src="https://ssl.daumcdn.net/dmaps/map_js_init/postcode.v2.js"></script>
<script type="text/javascript" src="/resources/js/jquery-3.6.0.js"></script>
<script type="text/javascript">
$(function(){
	//다음 우편번호 검색
	$("#btnPostno").on("click",function(){
		new daum.Postcode({
			//다음 창에서 검색이 완료되면 콜백함수에 의해 결과 데이터가 data 객체로 들어옴
			oncomplete:function(data){
				//우편번호
				$("#zipCode").val(data.zonecode);
				$("#address").val(data.address);
				$("#detAddress").val(data.buildingName);
			}
		}).open();
	});
	
	
	// 직원번호 자동등록
	// processType : false는 파일업로드 시 사용(let formData = new formData())
	// contentType : "application/json;charset:utf-8"(보내는 타입)
	// data : JSON.stringify(data);
	// type : "post"
	// success : function(){}
	$.ajax({
		url : "/emp/getEmpNum",
		type : "post",
		success: function(result){
			console.log("result : " + result);
			$("#empNumAjax").val(result);
		}
	});
});
</script>
<form:form modelAttribute="empVO" action="/emp/createPost" method="post"
		 class="row g-3">
	<!-- 직원번호 시작 -->
	<div class="col-md-6" style="clear:both;">
	  <label for="empNum" class="form-label">직원번호</label>
	  <input type="text" name="empNum" class="form-control" id="empNum"
	  	value="${empNum}" placeholder="직원번호를 입력해주세요" />
	  <form:input path="empNum" class="form-control" placeholder="직원번호를 입력해주세요" />
	  <input type="text" name="empNum" class="form-control" id="empNumAjax"
	  	value="" placeholder="직원번호를 입력해주세요" />
	</div>
	<!-- 직원번호 끝 -->
	<!-- 주소 시작 -->
	<div class="col-md-2">
    	<label for="zipCode" class="form-label">우편번호</label>
    	<input type="text" name="zipCode" class="form-control" id="zipCode"
    		placeholder="우편번호를 검색해주세요" />
    	<button type="button" class="btn btn-primary" id="btnPostno">검색</button>
	</div>
	<div class="col-12">
	    <label for="address" class="form-label">주소</label>
	    <input type="text" name="address" class="form-control" id="address" 
	    	placeholder="주소를 검색해주세요">
	</div>
	<div class="col-12">
	    <label for="detAddress" class="form-label">상세주소</label>
	    <input type="text" name="detAddress" class="form-control" id="detAddress" 
	    	placeholder="상세주소를 입력해주세요">
	</div>
    <!-- 주소 끝 -->
    <!-- 연락처 시작 -->
	<div class="col-md-6">
	  <label for="empPne" class="form-label">연락처</label>
	  <input type="text" name="empPne" class="form-control" id="empPne"
	  	placeholder="연락처를 입력해주세요" />
	</div>
	<!-- 연락처 끝 -->
    <!-- 직원명 시작 -->
	<div class="col-md-6">
	  <label for="empNm" class="form-label">직원명</label>
	  <input type="text" name="empNm" class="form-control" id="empNm"
	  	placeholder="직원명을 입력해주세요" />
	</div>
	<!-- 직원명 끝 -->
    <!-- 급여 시작 -->
	<div class="col-md-6">
	  <label for="empPay" class="form-label">급여</label>
	  <input type="number" name="empPay" class="form-control" id="empPay"
	  	placeholder="급여를 입력해주세요" />
	</div>
	<!-- 급여 끝 -->
	<div class="col-12">
	  <button type="submit" class="btn btn-primary">Sign in</button>
	</div>
</form:form>

 

<EmpController.java>

	//신규 직원번호 가져오기
	//요청URI : /emp/getEmpNum
	//요청방법 : post
	//ResponseBody : JSON데이터로 리턴
	@ResponseBody
	@PostMapping("/getEmpNum")
	public String getEmpNum() {
		String empNum = this.empService.getEmpNum();
		
		return empNum;
	}

package kr.or.ddit.controller;

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.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import kr.or.ddit.service.EmpService;
import kr.or.ddit.vo.EmpVO;

@RequestMapping("/emp")
@Controller
public class EmpController {
	@Autowired
	EmpService empService;
	
	//요청URI : /emp/create
	//요청방식 : get
	@GetMapping("/create")
	public String create(@ModelAttribute("empVO") EmpVO empVO
			, Model model) {
		
		//다음 직원번호를 가져옴
		//서비스의 메서드 호출
		String empNum = this.empService.getEmpNum();
		//1. <form:form modelAttribute="empVO"
		empVO.setEmpNum(empNum);
		//2. ${empNum} 를 사용하는 경우  ( value="${empNum}")
		model.addAttribute("empNum", empNum);		
		
		//forwarding
		return "emp/create";
	}
	
	//신규 직원번호 가져오기
	//요청URI : /emp/getEmpNum
	//요청방법 : post
	//ResponseBody : JSON데이터로 리턴
	@ResponseBody
	@PostMapping("/getEmpNum")
	public String getEmpNum() {
		String empNum = this.empService.getEmpNum();
		
		return empNum;
	}
}

실행하면 잘 들어감

 


매니저 등록

 

- 모달창 사용하기

https://getbootstrap.kr/docs/5.2/components/modal/

<!-- Modal -->
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h1 class="modal-title fs-5" id="exampleModalLabel">Modal title</h1>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        ...
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
        <button type="button" class="btn btn-primary">Save changes</button>
      </div>
    </div>
  </div>
</div>

 

 

<create.jsp>

<%@ page language="java" contentType="text/html;charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<link rel="stylesheet" href="/resources/css/bootstrap.min.css" />
<script src="https://ssl.daumcdn.net/dmaps/map_js_init/postcode.v2.js"></script>
<script type="text/javascript" src="/resources/js/jquery-3.6.0.js"></script>
<script type="text/javascript">
$(function(){
	//다음 우편번호 검색
	$("#btnPostno").on("click",function(){
		new daum.Postcode({
			//다음 창에서 검색이 완료되면 콜백함수에 의해 결과 데이터가 data 객체로 들어옴
			oncomplete:function(data){
				//우편번호
				$("#zipCode").val(data.zonecode);
				$("#address").val(data.address);
				$("#detAddress").val(data.buildingName);
			}
		}).open();
	});
	
	
	// 직원번호 자동등록
	// processType:false는 파일업로드 시 사용(let formData = new formData())
	// contentType:"application/json;charset:utf-8"(보내는 타입)
	// data:JSON.stringify(data);
	// type:"post"
	// success:function(){}
	$.ajax({
		url:"/emp/getEmpNum",
		type:"post",
		success:function(result){
			console.log("result : " + result);
			$("#empNumAjax").val(result);
		}
	});
});
</script>
<form:form modelAttribute="empVO" action="/emp/createPost" method="post"
		 class="row g-3">
	<!-- 직원번호 시작 -->
	<div class="col-md-6" style="clear:both;">
	  <label for="empNum" class="form-label">직원번호</label>
<!-- 	  <input type="text" name="empNum" class="form-control" id="empNum" -->
<%-- 	  	value="${empNum}" placeholder="직원번호를 입력해주세요" /> --%>
<%-- 	  <form:input path="empNum" class="form-control" placeholder="직원번호를 입력해주세요" /> --%>
	  <input type="text" name="empNum" class="form-control" id="empNumAjax"
	  	value="" placeholder="직원번호를 입력해주세요" />
	</div>
	<!-- 직원번호 끝 -->
	<!-- 주소 시작 -->
	<div class="col-md-2">
    	<label for="zipCode" class="form-label">우편번호</label>
    	<input type="text" name="zipCode" class="form-control" id="zipCode"
    		placeholder="우편번호를 검색해주세요" />
    	<button type="button" class="btn btn-primary" id="btnPostno">검색</button>
	</div>
	<div class="col-12">
	    <label for="address" class="form-label">주소</label>
	    <input type="text" name="address" class="form-control" id="address" 
	    	placeholder="주소를 검색해주세요">
	</div>
	<div class="col-12">
	    <label for="detAddress" class="form-label">상세주소</label>
	    <input type="text" name="detAddress" class="form-control" id="detAddress" 
	    	placeholder="상세주소를 입력해주세요">
	</div>
    <!-- 주소 끝 -->
    <!-- 연락처 시작 -->
	<div class="col-md-6">
	  <label for="empPne" class="form-label">연락처</label>
	  <input type="text" name="empPne" class="form-control" id="empPne"
	  	placeholder="연락처를 입력해주세요" />
	</div>
	<!-- 연락처 끝 -->
    <!-- 직원명 시작 -->
	<div class="col-md-6">
	  <label for="empNm" class="form-label">직원명</label>
	  <input type="text" name="empNm" class="form-control" id="empNm"
	  	placeholder="직원명을 입력해주세요" />
	</div>
	<!-- 직원명 끝 -->
    <!-- 급여 시작 -->
	<div class="col-md-6">
	  <label for="empPay" class="form-label">급여</label>
	  <input type="number" name="empPay" class="form-control" id="empPay"
	  	placeholder="급여를 입력해주세요" />
	</div>
	<!-- 급여 끝 -->
	<!-- 매니저 등록 시작 -->
	<div class="col-md-6">
	  <label for="empMjNm" class="form-label">매니저명</label>
	  <input type="text" name="empMjNum" class="form-control" id="empMjNum" />
	  <input type="text" class="form-control" id="empMjNm"
	  	placeholder="직원명을 입력해주세요" />
	  <button type="button" class="btn btn-primary" id="btnEmpMjNum"
	  	 data-toggle="modal" data-target="#exampleModal"
	  >검색</button>
	</div>
	<!-- 매니저 등록 끝 -->
	<div class="col-12">
	  <button type="submit" class="btn btn-primary">Sign in</button>
	</div>
</form:form>
<!-- Modal -->
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h1 class="modal-title fs-5" id="exampleModalLabel">Modal title</h1>
        <button type="button" class="btn-close" data-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        ...
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
        <button type="button" class="btn btn-primary">Save changes</button>
      </div>
    </div>
  </div>
</div>

 

 

이제 모달창에 직원이 나오게

등록을 해보자 !

 

<EmpController.java> 

  • createPost 매서드 생성
  • @valid 를 쓰면 @에 대한 유효성 검사를 해주고 errors라는 태그를 통해 에러를 확인할 수 있다.
  • errors를 쓰는경우 forwarding을 써준다.
	// 신규 직원 등록하기
	/*
	요청URI : /emp/createPost
	요청파라미터 : {empNum=EMP001,zipCode=12345,address=대전...,empMjNum=}
	요청방식 : post
	empMjNum=null => 일반직원
	*/
	@PostMapping("/createPost")
	public String createPost(@Valid @ModelAttribute EmpVO empVO,
			Errors errors) {
		log.info("empVO :" + empVO);
		
		if(errors.hasErrors()) {
			//forwarding
			return "emp/create";
		}
		
		//forwarding
		return "emp/detail";
	}

 

<emp_SQL.xml>

 

1. 첫번째 방식

<!-- 신규 직원 등록 -->
	<insert id="createPost" parameterType="empVO">
		<selectKey resultType="String" order="BEFORE" keyProperty="empNum">
			SELECT NVL(SUBSTR(MAX(EMP_NUM),1,3),'EMP')
    		 		|| TRIM(TO_CHAR(NVL(SUBSTR(MAX(EMP_NUM),4),0)+1,'000'))
			  FROM   EMP
		</selectKey>
		INSERT INTO EMP(EMP_NUM, EMP_ADDR, EMP_PNE, EMP_NM, EMP_PAY
						, EMP_MJ_NUM)
		VALUES(#{empNum},#{empAddr},#{empPne},#{empNm},#{empPay},#{empMjNum})
	</insert>

2. 두번째 방식(이걸로 선택함)

<!-- 신규 직원 등록 -->
	<insert id="createPost" parameterType="empVO">
		<selectKey resultType="String" order="BEFORE" keyProperty="empNum">
			SELECT NVL(SUBSTR(MAX(EMP_NUM),1,3),'EMP')
			     || TRIM(TO_CHAR(NVL(SUBSTR(MAX(EMP_NUM),4),0) + 1,'000'))
			FROM   EMP
		</selectKey>
	
		INSERT INTO EMP(EMP_NUM, EMP_ADDR, EMP_PNE, EMP_NM, EMP_PAY
				<if test="empMjNum!=null and empMjNum!=''">
				, EMP_MJ_NUM
				</if>
				)
		VALUES(#{empNum},#{empAddr}, #{empPne}, #{empNm}, #{empPay}
				<if test="empMjNum!=null and empMjNum!=''">
				, #{empMjNum}
				</if>
				)
	</insert>

 

<EmpMapper.java> 

// 신규 직원 등록 
	public int createPost(EmpVO empVO);

 

<EmpService.java>

	// 신규 직원 등록 
	public int createPost(EmpVO empVO);

<EmpServiceImpl.java>

// 신규 직원 등록 
	@Override
	public int createPost(EmpVO empVO) {
		return this.empMapper.createPost(empVO);
	}

 

<EmpController.java>

  • 우편번호 + 주소 + 상세주소
// 신규 직원 등록하기
	/*
	요청URI : /emp/createPost
	요청파라미터 : {empNum=EMP001,zipCode=12345,address=대전...,empMjNum=}
	요청방식 : post
	empMjNum=null => 일반직원
	String zipCode, String address, String detAddress => 멤버변수에 없으므로 파라미터로 직접 받음
	*/
	@PostMapping("/createPost")
	public String createPost(@Valid @ModelAttribute EmpVO empVO,
			String zipCode, String address, String detAddress,
			Errors errors) {
		log.info("empVO :" + empVO);
		
		if(errors.hasErrors()) {
			//forwarding
			return "emp/create";
		}
		
		// 우편번호 + 주소 + 상세주소 => empVO의 enpAddr 멤버변수에 setting 하기
		String empAddr = zipCode + " " + address + " " + detAddress;
		
		empVO.setEmpAddr(empAddr);
		
		int result = this.empService.createPost(empVO);
		
		return "redirect:/emp/detail?empNum="+empVO.getEmpNum();
	}

 

<create.jsp>

  • form:error를 넣어준다.
<%@ page language="java" contentType="text/html;charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<link rel="stylesheet" href="/resources/css/bootstrap.min.css" />
<script src="https://ssl.daumcdn.net/dmaps/map_js_init/postcode.v2.js"></script>
<script type="text/javascript" src="/resources/js/jquery-3.6.0.js"></script>
<script type="text/javascript">
$(function(){
	//다음 우편번호 검색
	$("#btnPostno").on("click",function(){
		new daum.Postcode({
			//다음 창에서 검색이 완료되면 콜백함수에 의해 결과 데이터가 data 객체로 들어옴
			oncomplete:function(data){
				//우편번호
				$("#zipCode").val(data.zonecode);
				$("#address").val(data.address);
				$("#detAddress").val(data.buildingName);
			}
		}).open();
	});
	
	
	// 직원번호 자동등록
	// processType:false는 파일업로드 시 사용(let formData = new formData())
	// contentType:"application/json;charset:utf-8"(보내는 타입)
	// data:JSON.stringify(data);
	// type:"post"
	// success:function(){}
	$.ajax({
		url:"/emp/getEmpNum",
		type:"post",
		success:function(result){
			console.log("result : " + result);
			$("#empNumAjax").val(result);
		}
	});
});
</script>
<!-- 요청URI : /emp/createPost
	요청파라미터 : {empNum=EMP001,zipCode=12345,address=대전...,empMjNum=}
	요청방식 : post
 -->
<form:form modelAttribute="empVO" action="/emp/createPost" method="post"
		 class="row g-3">
	<!-- 직원번호 시작 -->
	<div class="col-md-6" style="clear:both;">
	  <label for="empNum" class="form-label">직원번호</label>
<!-- 	  <input type="text" name="empNum" class="form-control" id="empNum" -->
<%-- 	  	value="${empNum}" placeholder="직원번호를 입력해주세요" /> --%>
<%-- 	  <form:input path="empNum" class="form-control" placeholder="직원번호를 입력해주세요" /> --%>
	  <input type="text" name="empNum" class="form-control" id="empNumAjax"
	  	value="" placeholder="직원번호를 입력해주세요" />
	</div>
	<!-- 직원번호 끝 -->
	<!-- 주소 시작 -->
	<div class="col-md-2">
    	<label for="zipCode" class="form-label">우편번호</label>
    	<input type="text" name="zipCode" class="form-control" id="zipCode"
    		placeholder="우편번호를 검색해주세요" />
    	<button type="button" class="btn btn-primary" id="btnPostno">검색</button>
	</div>
	<div class="col-12">
	    <label for="address" class="form-label">주소</label>
	    <input type="text" name="address" class="form-control" id="address" 
	    	placeholder="주소를 검색해주세요">
	</div>
	<div class="col-12">
	    <label for="detAddress" class="form-label">상세주소</label>
	    <input type="text" name="detAddress" class="form-control" id="detAddress" 
	    	placeholder="상세주소를 입력해주세요">
	</div>
    <!-- 주소 끝 -->
    <!-- 연락처 시작 -->
	<div class="col-md-6">
	  <label for="empPne" class="form-label">연락처</label>
	  <input type="text" name="empPne" class="form-control" id="empPne"
	  	placeholder="연락처를 입력해주세요" required />
	  <form:errors path="empPne" />
	</div>
	<!-- 연락처 끝 -->
    <!-- 직원명 시작 -->
	<div class="col-md-6">
	  <label for="empNm" class="form-label">직원명</label>
	  <input type="text" name="empNm" class="form-control" id="empNm"
	  	placeholder="직원명을 입력해주세요" required />
	  <form:errors path="empNm" />
	</div>
	<!-- 직원명 끝 -->
    <!-- 급여 시작 -->
	<div class="col-md-6">
	  <label for="empPay" class="form-label">급여</label>
	  <input type="number" name="empPay" class="form-control" id="empPay"
	  	placeholder="급여를 입력해주세요" required />
	  <form:errors path="empPay" />
	</div>
	<!-- 급여 끝 -->
	<!-- 매니저 등록 시작 -->
	<div class="col-md-6">
	  <label for="empMjNm" class="form-label">매니저명</label>
	  <input type="text" name="empMjNum" class="form-control" id="empMjNum" />
	  <input type="text" class="form-control" id="empMjNm"
	  	placeholder="직원명을 입력해주세요" />
	  <button type="button" class="btn btn-primary" id="btnEmpMjNum"
	  	 data-toggle="modal" data-target="#exampleModal"
	  >검색</button>
	</div>
	<!-- 매니저 등록 끝 -->
	<div class="col-12">
	  <button type="submit" class="btn btn-primary">등록</button>
	</div>
</form:form>
<!-- Modal -->
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h1 class="modal-title fs-5" id="exampleModalLabel">Modal title</h1>
        <button type="button" class="btn-close" data-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        ...
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
        <button type="button" class="btn btn-primary">Save changes</button>
      </div>
    </div>
  </div>
</div>

 

 


모든 직원 정보 가져오기 (모달창 출력)

 

<emp_SQL.xml>

<!-- 모든 직원 정보 가져오기 -->
	<select id="getEmpAll" resultType="empVO">
		SELECT EMP_NUM, EMP_ADDR, EMP_PNE, EMP_NM, EMP_PAY, EMP_MJ_NUM
		FROM EMP
		ORDER BY EMP_NUM
	</select>

<EmpMapper.java>

// 모든 직원 정보 가져오기
	public List<EmpVO> getEmpAll();

 

<EmpService.java>

	// 모든 직원 정보 가져오기
	public List<EmpVO> getEmpAll();

 

<EmpServiceImpl.java>

	// 모든 직원 정보 가져오기
	@Override
	public List<EmpVO> getEmpAll(){
		return this.empMapper.getEmpAll();
	}

 

<EmpController.java>

  • 직원목록을 json으로 받아보자
	/*
	 모든 직원 정보 가져오기
	 요청URI : /emp/getEmpAll
	 요청방식 : post
	dataType : json
	 */
	@ResponseBody
	@PostMapping("/getEmpAll")
	public List<EmpVO> getEmpALl(){
		// 모든 직원 정보 가져오기
		List<EmpVO> empVOList = this.empService.getEmpAll();
		
		log.info("empVOList : " + empVOList);
		
		return empVOList;
	}

 

 

- 부트스트랩 적용하기 (모달창 안에 목록)

- outer HTML 로 복사해서 가져오기

 

<create.jsp>

  • 매니저 선택하기 위한 ajax 식 작성

우선 콘솔로 찍어보자

<%@ page language="java" contentType="text/html;charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<link rel="stylesheet" href="/resources/css/bootstrap.min.css" />
<script src="https://ssl.daumcdn.net/dmaps/map_js_init/postcode.v2.js"></script>
<script type="text/javascript" src="/resources/js/jquery-3.6.0.js"></script>
<script type="text/javascript">
$(function(){
	//다음 우편번호 검색
	$("#btnPostno").on("click",function(){
		new daum.Postcode({
			//다음 창에서 검색이 완료되면 콜백함수에 의해 결과 데이터가 data 객체로 들어옴
			oncomplete:function(data){
				//우편번호
				$("#zipCode").val(data.zonecode);
				$("#address").val(data.address);
				$("#detAddress").val(data.buildingName);
			}
		}).open();
	});
	
	
	// 직원번호 자동등록
	// processType:false는 파일업로드 시 사용(let formData = new formData())
	// contentType:"application/json;charset:utf-8"(보내는 타입)
	// data:JSON.stringify(data);
	// type:"post"
	// success:function(){}
	$.ajax({
		url:"/emp/getEmpNum",
		type:"post",
		success:function(result){
			console.log("result : " + result);
			$("#empNumAjax").val(result);
		}
	});
	
	// 매니저 선택하기
	$("#btnEmpMjNum").on("click",function(){
		$.ajax({
			url:"/emp/getEmpAll",
			type:"post",
			success:function(result){
				//result : List<EmpVO> empVOList
				$.each(result, function(index, empVO){
					console.log("empVO.empNum :" + empVO.empNum);
					console.log("empVO.empNm :" + empVO.empNm);
				});
			
			}
		});
	});
});
</script>
<!-- 요청URI : /emp/createPost
	요청파라미터 : {empNum=EMP001,zipCode=12345,address=대전...,empMjNum=}
	요청방식 : post
 -->
<form:form modelAttribute="empVO" action="/emp/createPost" method="post"
		 class="row g-3">
	<!-- 직원번호 시작 -->
	<div class="col-md-6" style="clear:both;">
	  <label for="empNum" class="form-label">직원번호</label>
<!-- 	  <input type="text" name="empNum" class="form-control" id="empNum" -->
<%-- 	  	value="${empNum}" placeholder="직원번호를 입력해주세요" /> --%>
<%-- 	  <form:input path="empNum" class="form-control" placeholder="직원번호를 입력해주세요" /> --%>
	  <input type="text" name="empNum" class="form-control" id="empNumAjax"
	  	value="" placeholder="직원번호를 입력해주세요" />
	</div>
	<!-- 직원번호 끝 -->
	<!-- 주소 시작 -->
	<div class="col-md-2">
    	<label for="zipCode" class="form-label">우편번호</label>
    	<input type="text" name="zipCode" class="form-control" id="zipCode"
    		placeholder="우편번호를 검색해주세요" />
    	<button type="button" class="btn btn-primary" id="btnPostno">검색</button>
	</div>
	<div class="col-12">
	    <label for="address" class="form-label">주소</label>
	    <input type="text" name="address" class="form-control" id="address" 
	    	placeholder="주소를 검색해주세요">
	</div>
	<div class="col-12">
	    <label for="detAddress" class="form-label">상세주소</label>
	    <input type="text" name="detAddress" class="form-control" id="detAddress" 
	    	placeholder="상세주소를 입력해주세요">
	</div>
    <!-- 주소 끝 -->
    <!-- 연락처 시작 -->
	<div class="col-md-6">
	  <label for="empPne" class="form-label">연락처</label>
	  <input type="text" name="empPne" class="form-control" id="empPne"
	  	placeholder="연락처를 입력해주세요" required />
	  <form:errors path="empPne" />
	</div>
	<!-- 연락처 끝 -->
    <!-- 직원명 시작 -->
	<div class="col-md-6">
	  <label for="empNm" class="form-label">직원명</label>
	  <input type="text" name="empNm" class="form-control" id="empNm"
	  	placeholder="직원명을 입력해주세요" required />
	  <form:errors path="empNm" />
	</div>
	<!-- 직원명 끝 -->
    <!-- 급여 시작 -->
	<div class="col-md-6">
	  <label for="empPay" class="form-label">급여</label>
	  <input type="number" name="empPay" class="form-control" id="empPay"
	  	placeholder="급여를 입력해주세요" required />
	  <form:errors path="empPay" />
	</div>
	<!-- 급여 끝 -->
	<!-- 매니저 등록 시작 -->
	<div class="col-md-6">
	  <label for="empMjNm" class="form-label">매니저명</label>
	  <input type="text" name="empMjNum" class="form-control" id="empMjNum" />
	  <input type="text" class="form-control" id="empMjNm"
	  	placeholder="직원명을 입력해주세요" />
	  <button type="button" class="btn btn-primary" id="btnEmpMjNum"
	  	 data-toggle="modal" data-target="#exampleModal"
	  >검색</button>
	</div>
	<!-- 매니저 등록 끝 -->
	<div class="col-12">
	  <button type="submit" class="btn btn-primary">등록</button>
	</div>
</form:form>
<!-- Modal -->
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h1 class="modal-title fs-5" id="exampleModalLabel">Modal title</h1>
        <button type="button" class="btn-close" data-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        <!-- -------- 직원 목록 시작 ------------- -->
        <div class="bd-example">
		  <table class="table table-hover">
		      <thead>
		    <tr>
		      <th scope="col">#</th>
		      <th scope="col">직원번호</th>
		      <th scope="col">이름</th>
		    </tr>
		  </thead>
		  <tbody>
		    <tr>
		      <th scope="row">1</th>
		      <td>Mark</td>
		      <td>Otto</td>
		    </tr>
		  </tbody>
		  </table>
		</div>
        <!-- -------- 직원 목록 끝 ------------- -->
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
        <button type="button" class="btn btn-primary">Save changes</button>
      </div>
    </div>
  </div>
</div>

실행시키면 잘 출력됨

 

tbody에 아이디를 준다.

 

<create.jsp> 추가

	// 매니저 선택하기
	$("#btnEmpMjNum").on("click",function(){
		$.ajax({
			url:"/emp/getEmpAll",
			type:"post",
			success:function(result){
				//result : List<EmpVO> empVOList
				let str = "";
				
				$.each(result, function(index, empVO){
					console.log("empVO.empNum :" + empVO.empNum);
					console.log("empVO.empNm :" + empVO.empNm);
					
					str += "<tr><th scope='row'>"+(index+1)+"</th>";
					str += "<td>"+empVO.empNum+"</td><td>"+empVO.empNm+"</td></tr>";
				});
				
				console.log("str :" + str);
				//.html() : 새로고침 / .append() : 누적
				$("#trAdd").html(str); // 초기화
				//$("#trAdd").append(str);
			}
		});
	});

 

 

 

 


동적 요소 이벤트 처리

<create.jsp> 추가

	// 동적으로 생성된 요소의 이벤트 처리
	//  $(".trSelect").on("click",function(){})은 작동을 안할것임
	   $(document).on("click",".trSelect",function(){
	      //this : tr이 여러개인데 그 중 클릭한 바로 그 tr
	      //td들을 가져옴. 그 안에 데이터를 가져와보자
	      let resultStr = $(this).children().map(function(){
	         return $(this).text();}).get().join(",");
	      console.log("resultStr : " + resultStr);
	   });

<%@ page language="java" contentType="text/html;charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<link rel="stylesheet" href="/resources/css/bootstrap.min.css" />
<script src="https://ssl.daumcdn.net/dmaps/map_js_init/postcode.v2.js"></script>
<script type="text/javascript" src="/resources/js/jquery-3.6.0.js"></script>
<script type="text/javascript">
$(function(){
	//다음 우편번호 검색
	$("#btnPostno").on("click",function(){
		new daum.Postcode({
			//다음 창에서 검색이 완료되면 콜백함수에 의해 결과 데이터가 data 객체로 들어옴
			oncomplete:function(data){
				//우편번호
				$("#zipCode").val(data.zonecode);
				$("#address").val(data.address);
				$("#detAddress").val(data.buildingName);
			}
		}).open();
	});
	
	
	// 직원번호 자동등록
	// processType:false는 파일업로드 시 사용(let formData = new formData())
	// contentType:"application/json;charset:utf-8"(보내는 타입)
	// data:JSON.stringify(data);
	// type:"post"
	// success:function(){}
	$.ajax({
		url:"/emp/getEmpNum",
		type:"post",
		success:function(result){
			console.log("result : " + result);
			$("#empNumAjax").val(result);
		}
	});
	
	// 매니저 선택하기
	$("#btnEmpMjNum").on("click",function(){
		$.ajax({
			url:"/emp/getEmpAll",
			type:"post",
			success:function(result){
				//result : List<EmpVO> empVOList
				let str = "";
				
				$.each(result, function(index, empVO){
					console.log("empVO.empNum :" + empVO.empNum);
					console.log("empVO.empNm :" + empVO.empNm);
					
					str += "<tr class='trSelect'><th scope='row'>"+(index+1)+"</th>";
					str += "<td>"+empVO.empNum+"</td><td>"+empVO.empNm+"</td></tr>";
				});
				
				console.log("str :" + str);
				//.html() : 새로고침 / .append() : 누적
				$("#trAdd").html(str); // 초기화
				//$("#trAdd").append(str);
			}
		});
	});
	
	// 동적으로 생성된 요소의 이벤트 처리
	//  $(".trSelect").on("click",function(){})은 작동을 안할것임
	   $(document).on("click",".trSelect",function(){
	      //this : tr이 여러개인데 그 중 클릭한 바로 그 tr
	      //td들을 가져옴. 그 안에 데이터를 가져와보자
	      let resultStr = $(this).children().map(function(){
	         return $(this).text();}).get().join(",");
	      console.log("resultStr : " + resultStr);
	   });
});
</script>
<!-- 요청URI : /emp/createPost
	요청파라미터 : {empNum=EMP001,zipCode=12345,address=대전...,empMjNum=}
	요청방식 : post
 -->
<form:form modelAttribute="empVO" action="/emp/createPost" method="post"
		 class="row g-3">
	<!-- 직원번호 시작 -->
	<div class="col-md-6" style="clear:both;">
	  <label for="empNum" class="form-label">직원번호</label>
<!-- 	  <input type="text" name="empNum" class="form-control" id="empNum" -->
<%-- 	  	value="${empNum}" placeholder="직원번호를 입력해주세요" /> --%>
<%-- 	  <form:input path="empNum" class="form-control" placeholder="직원번호를 입력해주세요" /> --%>
	  <input type="text" name="empNum" class="form-control" id="empNumAjax"
	  	value="" placeholder="직원번호를 입력해주세요" />
	</div>
	<!-- 직원번호 끝 -->
	<!-- 주소 시작 -->
	<div class="col-md-2">
    	<label for="zipCode" class="form-label">우편번호</label>
    	<input type="text" name="zipCode" class="form-control" id="zipCode"
    		placeholder="우편번호를 검색해주세요" />
    	<button type="button" class="btn btn-primary" id="btnPostno">검색</button>
	</div>
	<div class="col-12">
	    <label for="address" class="form-label">주소</label>
	    <input type="text" name="address" class="form-control" id="address" 
	    	placeholder="주소를 검색해주세요">
	</div>
	<div class="col-12">
	    <label for="detAddress" class="form-label">상세주소</label>
	    <input type="text" name="detAddress" class="form-control" id="detAddress" 
	    	placeholder="상세주소를 입력해주세요">
	</div>
    <!-- 주소 끝 -->
    <!-- 연락처 시작 -->
	<div class="col-md-6">
	  <label for="empPne" class="form-label">연락처</label>
	  <input type="text" name="empPne" class="form-control" id="empPne"
	  	placeholder="연락처를 입력해주세요" required />
	  <form:errors path="empPne" />
	</div>
	<!-- 연락처 끝 -->
    <!-- 직원명 시작 -->
	<div class="col-md-6">
	  <label for="empNm" class="form-label">직원명</label>
	  <input type="text" name="empNm" class="form-control" id="empNm"
	  	placeholder="직원명을 입력해주세요" required />
	  <form:errors path="empNm" />
	</div>
	<!-- 직원명 끝 -->
    <!-- 급여 시작 -->
	<div class="col-md-6">
	  <label for="empPay" class="form-label">급여</label>
	  <input type="number" name="empPay" class="form-control" id="empPay"
	  	placeholder="급여를 입력해주세요" required />
	  <form:errors path="empPay" />
	</div>
	<!-- 급여 끝 -->
	<!-- 매니저 등록 시작 -->
	<div class="col-md-6">
	  <label for="empMjNm" class="form-label">매니저명</label>
	  <input type="text" name="empMjNum" class="form-control" id="empMjNum" />
	  <input type="text" class="form-control" id="empMjNm"
	  	placeholder="직원명을 입력해주세요" />
	  <button type="button" class="btn btn-primary" id="btnEmpMjNum"
	  	 data-toggle="modal" data-target="#exampleModal"
	  >검색</button>
	</div>
	<!-- 매니저 등록 끝 -->
	<div class="col-12">
	  <button type="submit" class="btn btn-primary">등록</button>
	</div>
</form:form>
<!-- Modal -->
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h1 class="modal-title fs-5" id="exampleModalLabel">Modal title</h1>
        <button type="button" class="btn-close" data-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        <!-- -------- 직원 목록 시작 ------------- -->
        <div class="bd-example">
		  <table class="table table-hover">
		      <thead>
		    <tr>
		      <th scope="col">#</th>
		      <th scope="col">직원번호</th>
		      <th scope="col">이름</th>
		    </tr>
		  </thead>
		  <tbody id="trAdd">
		    <tr>
		      <th scope="row">1</th>
		      <td></td>
		      <td></td>
		    </tr>
		  </tbody>
		  </table>
		</div>
        <!-- -------- 직원 목록 끝 ------------- -->
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
        <button type="button" class="btn btn-primary">Save changes</button>
      </div>
    </div>
  </div>
</div>

클릭시 이벤트

 

	
	// 동적으로 생성된 요소의 이벤트 처리
	//  $(".trSelect").on("click",function(){})은 작동을 안할것임
	   $(document).on("click",".trSelect",function(){
	      //this : tr이 여러개인데 그 중 클릭한 바로 그 tr
	      //td들을 가져옴. 그 안에 데이터를 가져와보자
	      let resultStr = $(this).children().map(function(){
	         return $(this).text();}).get().join(",");
	      console.log("resultStr : " + resultStr);
	      
	      //resultStr : 4, EMP004, 훈이 => split(",")을 사용해서 배열로 만들고
	      // [1]는 매니저번호(empMjNum)로 입력, [2]는 매 니저명(empMjNm)으로 입력
	      // arr[0] : 4 / arr[1] : EMP004 /arr[2] : 훈이
	      let arr = resultStr.split(",");
	      $("#empMjNum").val(arr[1]);
	      $("#empMjNm").val(arr[2]);
	   });

 

그 다음

  • 직원번호, 우편번호, 주소, 매니저명 readonly 속성 추가
  • 매니저명은 input type="hidden"을 준다.

<%@ page language="java" contentType="text/html;charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<link rel="stylesheet" href="/resources/css/bootstrap.min.css" />
<script src="https://ssl.daumcdn.net/dmaps/map_js_init/postcode.v2.js"></script>
<script type="text/javascript" src="/resources/js/jquery-3.6.0.js"></script>
<script type="text/javascript">
$(function(){
	//다음 우편번호 검색
	$("#btnPostno").on("click",function(){
		new daum.Postcode({
			//다음 창에서 검색이 완료되면 콜백함수에 의해 결과 데이터가 data 객체로 들어옴
			oncomplete:function(data){
				//우편번호
				$("#zipCode").val(data.zonecode);
				$("#address").val(data.address);
				$("#detAddress").val(data.buildingName);
			}
		}).open();
	});
	
	
	// 직원번호 자동등록
	// processType:false는 파일업로드 시 사용(let formData = new formData())
	// contentType:"application/json;charset:utf-8"(보내는 타입)
	// data:JSON.stringify(data);
	// type:"post"
	// success:function(){}
	$.ajax({
		url:"/emp/getEmpNum",
		type:"post",
		success:function(result){
			console.log("result : " + result);
			$("#empNumAjax").val(result);
		}
	});
	
	// 매니저 선택하기
	$("#btnEmpMjNum").on("click",function(){
		$.ajax({
			url:"/emp/getEmpAll",
			type:"post",
			success:function(result){
				//result : List<EmpVO> empVOList
				let str = "";
				
				$.each(result, function(index, empVO){
					console.log("empVO.empNum :" + empVO.empNum);
					console.log("empVO.empNm :" + empVO.empNm);
					
					str += "<tr class='trSelect'><th scope='row'>"+(index+1)+"</th>";
					str += "<td>"+empVO.empNum+"</td><td>"+empVO.empNm+"</td></tr>";
				});
				
				console.log("str :" + str);
				//.html() : 새로고침 / .append() : 누적
				$("#trAdd").html(str); // 초기화
				//$("#trAdd").append(str);
			}
		});
	});
	
	// 동적으로 생성된 요소의 이벤트 처리
	//  $(".trSelect").on("click",function(){})은 작동을 안할것임
	   $(document).on("click",".trSelect",function(){
	      //this : tr이 여러개인데 그 중 클릭한 바로 그 tr
	      //td들을 가져옴. 그 안에 데이터를 가져와보자
	      let resultStr = $(this).children().map(function(){
	         return $(this).text();}).get().join(",");
	      console.log("resultStr : " + resultStr);
	      
	      //resultStr : 4, EMP004, 훈이 => split(",")을 사용해서 배열로 만들고
	      // [1]는 매니저번호(empMjNum)로 입력, [2]는 매 니저명(empMjNm)으로 입력
	      // arr[0] : 4 / arr[1] : EMP004 /arr[2] : 훈이
	      let arr = resultStr.split(",");
	      $("#empMjNum").val(arr[1]);
	      $("#empMjNm").val(arr[2]);
	   });
});
</script>
<!-- 요청URI : /emp/createPost
	요청파라미터 : {empNum=EMP001,zipCode=12345,address=대전...,empMjNum=}
	요청방식 : post
 -->
<form:form modelAttribute="empVO" action="/emp/createPost" method="post"
		 class="row g-3">
	<!-- 직원번호 시작 -->
	<div class="col-md-6" style="clear:both;">
	  <label for="empNum" class="form-label">직원번호</label>
<!-- 	  <input type="text" name="empNum" class="form-control" id="empNum" -->
<%-- 	  	value="${empNum}" placeholder="직원번호를 입력해주세요" /> --%>
<%-- 	  <form:input path="empNum" class="form-control" placeholder="직원번호를 입력해주세요" /> --%>
	  <input type="text" name="empNum" class="form-control" id="empNumAjax"
	  	value="" placeholder="직원번호를 입력해주세요" readonly/>
	</div>
	<!-- 직원번호 끝 -->
	<!-- 주소 시작 -->
	<div class="col-md-2">
    	<label for="zipCode" class="form-label">우편번호</label>
    	<input type="text" name="zipCode" class="form-control" id="zipCode"
    		placeholder="우편번호를 검색해주세요"  readonly/>
    	<button type="button" class="btn btn-primary" id="btnPostno">검색</button>
	</div>
	<div class="col-12">
	    <label for="address" class="form-label">주소</label>
	    <input type="text" name="address" class="form-control" id="address" 
	    	placeholder="주소를 검색해주세요" readonly>
	</div>
	<div class="col-12">
	    <label for="detAddress" class="form-label">상세주소</label>
	    <input type="text" name="detAddress" class="form-control" id="detAddress" 
	    	placeholder="상세주소를 입력해주세요">
	</div>
    <!-- 주소 끝 -->
    <!-- 연락처 시작 -->
	<div class="col-md-6">
	  <label for="empPne" class="form-label">연락처</label>
	  <input type="text" name="empPne" class="form-control" id="empPne"
	  	placeholder="연락처를 입력해주세요" required />
	  <form:errors path="empPne" />
	</div>
	<!-- 연락처 끝 -->
    <!-- 직원명 시작 -->
	<div class="col-md-6">
	  <label for="empNm" class="form-label">직원명</label>
	  <input type="text" name="empNm" class="form-control" id="empNm"
	  	placeholder="직원명을 입력해주세요" required />
	  <form:errors path="empNm" />
	</div>
	<!-- 직원명 끝 -->
    <!-- 급여 시작 -->
	<div class="col-md-6">
	  <label for="empPay" class="form-label">급여</label>
	  <input type="number" name="empPay" class="form-control" id="empPay"
	  	placeholder="급여를 입력해주세요" required />
	  <form:errors path="empPay" />
	</div>
	<!-- 급여 끝 -->
	<!-- 매니저 등록 시작 -->
	<div class="col-md-6">
	  <label for="empMjNm" class="form-label">매니저명</label>
	  <input type="hidden" name="empMjNum" class="form-control" id="empMjNum" />
	  <input type="text" class="form-control" id="empMjNm"
	  	placeholder="직원명을 입력해주세요" readonly />
	  <button type="button" class="btn btn-primary" id="btnEmpMjNum"
	  	 data-toggle="modal" data-target="#exampleModal"
	  >검색</button>
	</div>
	<!-- 매니저 등록 끝 -->
	<div class="col-12">
	  <button type="submit" class="btn btn-primary">등록</button>
	</div>
</form:form>
<!-- Modal -->
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h1 class="modal-title fs-5" id="exampleModalLabel">Modal title</h1>
        <button type="button" class="btn-close" data-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        <!-- -------- 직원 목록 시작 ------------- -->
        <div class="bd-example">
		  <table class="table table-hover">
		      <thead>
		    <tr>
		      <th scope="col">#</th>
		      <th scope="col">직원번호</th>
		      <th scope="col">이름</th>
		    </tr>
		  </thead>
		  <tbody id="trAdd">
		    <tr>
		      <th scope="row">1</th>
		      <td></td>
		      <td></td>
		    </tr>
		  </tbody>
		  </table>
		</div>
        <!-- -------- 직원 목록 끝 ------------- -->
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
        <button type="button" class="btn btn-primary">Save changes</button>
      </div>
    </div>
  </div>
</div>

detail 만들기

 

<EmpController.java>

//직원 상세보기
	/*
	 요청URI : /emp/detail?empNum=EMP006
	 요청파라미터 : empNum=EMP007
	 요청방식 :get
	 */
	@GetMapping("/detail")
	public String detail(@RequestParam String empNum
			, @ModelAttribute EmpVO empVO) {
		log.info("empNum : " + empNum);
		log.info("empVO : " + empVO);
		
		// 상세화면은 등록화면과 동일 + empVO데이터로 채우면 됨
		
		
		// emp 폴더의 detail.jsp를 forwarding
		return "emp/detail";
	}

 

직원 상세 보기 <쿼리문>

SELECT A.EMP_NUM, A.EMP_ADDR, A.EMP_PNE, A.EMP_NM, A.EMP_PAY, A.EMP_MJ_NUM
FROM   EMP A
WHERE A.EMP_NUM = 'EMP006'
OR    A.EMP_NUM = (
        SELECT B.EMP_MJ_NUM FROM EMP B WHERE B.EMP_NUM = 'EMP006'
);

 

<emp_SQL.xml>

<!-- 직원 상세 보기 (관리자가 있으면 관리자 정보도 포함) 
		empVO[empNum:EMP006, empAddr:null, empPne:null....]
	 ==> 들어올 땐 empNum만 들어오고 나갈땐 리스트가 채워져서 나간다.
	-->
	<select id="detail" parameterType="empVO" resultType="empVO">
		SELECT A.EMP_NUM, A.EMP_ADDR, A.EMP_PNE, A.EMP_NM, A.EMP_PAY, A.EMP_MJ_NUM
		FROM   EMP A
		WHERE  A.EMP_NUM = #{empNum}
		OR     A.EMP_NUM = (
		        SELECT B.EMP_MJ_NUM FROM EMP B WHERE B.EMP_NUM = #{empNum}
			)
	</select>

 

<EmpMapper.java>

// 직원  상세 보기 (관리자가 있으면 관리자 정보도 포함) 
	public List<EmpVO> detail(EmpVO empVO);

 

<EmpServiceImpl.java>

// 직원  상세 보기 (관리자가 있으면 관리자 정보도 포함) 
	@Override
	public List<EmpVO> detail(EmpVO empVO){
		return this.empMapper.detail(empVO);
	}

 

<EmpService.java>

// 직원  상세 보기 (관리자가 있으면 관리자 정보도 포함) 
	public List<EmpVO> detail(EmpVO empVO);

 

<EmpController.java>

//직원 상세보기
	/*
	 요청URI : /emp/detail?empNum=EMP006
	 요청파라미터 : empNum=EMP007
	 요청방식 :get
	 */
	@GetMapping("/detail")
	public String detail(@RequestParam String empNum
			, @ModelAttribute EmpVO empVO, Model model) {
		log.info("empNum : " + empNum);
		log.info("empVO : " + empVO);
		
		// 상세화면은 등록화면과 동일 + empVO데이터로 채우면 됨
		List<EmpVO> empVOList = this.empService.detail(empVO);
		log.info("empVOList : " + empVOList);
		
		model.addAttribute("data", empVOList);
		
		// emp 폴더의 detail.jsp를 forwarding
		return "emp/detail";
	}

 

 

detail.jsp 생성 (create.jsp복사)

 

 

- 부트스트랩 적용

https://getbootstrap.kr/docs/5.2/components/navs-tabs/

-컴포넌트=-> 네비게이션탭

<ul class="nav nav-tabs">
  <li class="nav-item">
    <a class="nav-link active" aria-current="page" href="#">Active</a>
  </li>
  <li class="nav-item">
    <a class="nav-link" href="#">Link</a>
  </li>
  <li class="nav-item">
    <a class="nav-link" href="#">Link</a>
  </li>
  <li class="nav-item">
    <a class="nav-link disabled">Disabled</a>
  </li>
</ul>

 

복사해서

form 태그 위에 복붙

  • <script type="text/javascript" src="/resources/js/bootstrap.min.js"></script> 상단에 추가

 

 

 


직원 , 관리자 탭을 클릭했을 때 active

 

  • toggleClass() 메서드는 해당 클래스를 토글함
  • removeAttr(): 선택한 요소에서 하나 이상의 특성을 제거함
  •  attr() : 선택한 요소의 속성을 추가

	$(".nav-link").on("click",function(){
		// toggleClass() 메서드는 해당 클래스를 토글함
		$(".link").toggleClass("active");
		// removeAttr(): 선택한 요소에서 하나 이상의 특성을 제거함
		$(".link").removeAttr("aria=current");
		// attr() : 선택한 요소의 속성을 추가
		$(this).attr("aria-current","page");
	});
});
</script>
<!-- 요청URI : /emp/createPost
	요청파라미터 : {empNum=EMP001,zipCode=12345,address=대전...,empMjNum=}
	요청방식 : post
 -->
 <ul class="nav nav-tabs">
  <li class="nav-item">
    <a class="nav-link link active" aria-current="page" href="#">직원</a>
  </li>
  <li class="nav-item">
    <a class="nav-link link" href="#">관리자</a>
  </li>
</ul>

 


  • 직원과 관리자에 div를 주고 스크립트 작성
$(".nav-link").on("click",function(){
		//toggleClass() 메서드는 해당 클래스를 토글함
		$(".link").toggleClass("active");
		//removeAttr() : 선택한 요소에서 하나 이상의 특성을 제거함
		$(".link").removeAttr("aria-current");
		//attr() : 선택한 요소의 속성을 추가함
		$(this).attr("aria-current","page");
		//this : link 클래스는 2개. 그 중에서 클릭한 바로 그 요소
		let id = $(this).data("id");  //employee 또는 manager
		if(id=="employee"){ // 직원 탭의 경우 직원 div를 보여주고, 관리자 div는 hidden처리함
			$("#employee").css("display","block");
			$("#manager").css("display","none");
		}else{ //관리자의 탭의 경우 관리자 div를 보여주고, 직원 div는 hidden처리함
			$("#employee").css("display","none");
			$("#manager").css("display","block");
		}
	});

<%@ page language="java" contentType="text/html;charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<link rel="stylesheet" href="/resources/css/bootstrap.min.css" />
<script type="text/javascript" src="/resources/js/bootstrap.min.js"></script>
<script src="https://ssl.daumcdn.net/dmaps/map_js_init/postcode.v2.js"></script>
<script type="text/javascript" src="/resources/js/jquery-3.6.0.js"></script>
<script type="text/javascript">
$(function(){
	//다음 우편번호 검색
	$("#btnPostno").on("click",function(){
		new daum.Postcode({
			//다음 창에서 검색이 완료되면 콜백함수에 의해 결과 데이터가 data 객체로 들어옴
			oncomplete:function(data){
				//우편번호
				$("#zipCode").val(data.zonecode);
				$("#address").val(data.address);
				$("#detAddress").val(data.buildingName);
			}
		}).open();
	});
	
	
	//직원번호 자동등록
	// processType:false는 파일업로드 시 사용(let formData = new formData())
	// contentType:"application/json;charset:utf-8"(보내는 타입)
	// data:JSON.stringify(data);
	// type:"post"
	// success:function(){}
	$.ajax({
		url:"/emp/getEmpNum",
		type:"post",
		success:function(result){
			console.log("result : " + result);
			$("#empNumAjax").val(result);
		}
	});
	
	//매니저 선택하기
	$("#btnEmpMjNum").on("click",function(){
		$.ajax({
			url:"/emp/getEmpAll",
			type:"post",
			success:function(result){
				//result : List<EmpVO> empVOList
				let str = "";
				
				$.each(result,function(index, empVO){
					console.log("empVO.empNum : " + empVO.empNum);
					console.log("empVO.empNm : " + empVO.empNm);
					//<th scope="row"> : 해당 셀이 행(row)을 위한 헤더 셀임을 명시함.
					str += "<tr class='trSelect'><th scope='col'>"+(index+1)+"</th>";
					str += "<td>"+empVO.empNum+"</td><td>"+empVO.empNm+"</td></tr>";
				});
				
				console.log("str : " + str);
				//.html() : 새로고침 / .append() : 누적
				$("#trAdd").html(str);	//초기화
// 				$("#trAdd").append(str);
			}
		});
	});
	
	//동적으로 생성된 요소의 이벤트 처리
// 	달러(".trSelect").on("click",function(){})은 작동을 안할것임
	$(document).on("click",".trSelect",function(){
		//this : tr이 여러개인데 그 중 클릭한 바로 그 tr
		//td들을 가져옴. 그 안에 데이터를 가져와보자
		let resultStr = $(this).children().map(function(){
			return $(this).text();}).get().join(",");
		console.log("resultStr : " + resultStr);
		
		//resultStr : 5,EMP005,이정재 => split(",")을 해서 배열로 만들고
		//[1]는 매니저번호(empMjNum)로 입력, [2]는 매니저명(empMjNm)으로 입력
		//arr[0] : 5 / arr[1] : EMP005 / arr[2] : 이정재
		let arr = resultStr.split(",");
		$("#empMjNum").val(arr[1]);
		$("#empMjNm").val(arr[2]);
	});
	
	$(".nav-link").on("click",function(){
		//toggleClass() 메서드는 해당 클래스를 토글함
		$(".link").toggleClass("active");
		//removeAttr() : 선택한 요소에서 하나 이상의 특성을 제거함
		$(".link").removeAttr("aria-current");
		//attr() : 선택한 요소의 속성을 추가함
		$(this).attr("aria-current","page");
		//this : link 클래스는 2개. 그 중에서 클릭한 바로 그 요소
		let id = $(this).data("id");  //employee 또는 manager
		if(id=="employee"){ // 직원 탭의 경우 직원 div를 보여주고, 관리자 div는 hidden처리함
			$("#employee").css("display","block");
			$("#manager").css("display","none");
		}else{ //관리자의 탭의 경우 관리자 div를 보여주고, 직원 div는 hidden처리함
			$("#employee").css("display","none");
			$("#manager").css("display","block");
		}
	});
});
</script>
<!-- 요청URI : /emp/createPost
	요청파라미터 : {empNum=EMP001,zipCode=12345,address=대전...,empMjNum=}
	요청방식 : post
 -->
<ul class="nav nav-tabs">
  <li class="nav-item">
    <a class="nav-link link active" data-id="employee" aria-current="page" href="#">직원</a>
  </li>
  <li class="nav-item">
    <a class="nav-link link" data-id="manager" href="#">관리자</a>
  </li>
</ul>

<div class="bd-example" id="employee">
<form:form modelAttribute="empVO" action="/emp/createPost" method="post"
		 class="row g-3">
	<!-- 직원번호 시작 -->
	<div class="col-md-6" style="clear:both;">
	  <label for="empNum" class="form-label">직원번호</label>
<!-- 	  <input type="text" name="empNum" class="form-control" id="empNum" -->
<%-- 	  	value="${empNum}" placeholder="직원번호를 입력해주세요" /> --%>
<%-- 	  <form:input path="empNum" class="form-control" placeholder="직원번호를 입력해주세요" /> --%>
	  <input type="text" name="empNum" class="form-control" id="empNumAjax"
	  	value="" placeholder="직원번호를 입력해주세요" readonly />
	</div>
	<!-- 직원번호 끝 -->
	<!-- 주소 시작 -->
	<div class="col-md-2">
    	<label for="zipCode" class="form-label">우편번호</label>
    	<input type="text" name="zipCode" class="form-control" id="zipCode"
    		placeholder="우편번호를 검색해주세요" readonly />
    	<button type="button" class="btn btn-primary" id="btnPostno">검색</button>
	</div>
	<div class="col-12">
	    <label for="address" class="form-label">주소</label>
	    <input type="text" name="address" class="form-control" id="address" 
	    	placeholder="주소를 검색해주세요" readonly />
	</div>
	<div class="col-12">
	    <label for="detAddress" class="form-label">상세주소</label>
	    <input type="text" name="detAddress" class="form-control" id="detAddress" 
	    	placeholder="상세주소를 입력해주세요">
	</div>
    <!-- 주소 끝 -->
    <!-- 연락처 시작 -->
	<div class="col-md-6">
	  <label for="empPne" class="form-label">연락처</label>
	  <input type="text" name="empPne" class="form-control" id="empPne"
	  	placeholder="연락처를 입력해주세요" required />
	  <form:errors path="empPne" />
	</div>
	<!-- 연락처 끝 -->
    <!-- 직원명 시작 -->
	<div class="col-md-6">
	  <label for="empNm" class="form-label">직원명</label>
	  <input type="text" name="empNm" class="form-control" id="empNm"
	  	placeholder="직원명을 입력해주세요" required />
	  <form:errors path="empNm" />
	</div>
	<!-- 직원명 끝 -->
    <!-- 급여 시작 -->
	<div class="col-md-6">
	  <label for="empPay" class="form-label">급여</label>
	  <input type="number" name="empPay" class="form-control" id="empPay"
	  	placeholder="급여를 입력해주세요" required />
	  <form:errors path="empPay" />
	</div>
	<!-- 급여 끝 -->
	<!-- 매니저 등록 시작 -->
	<div class="col-md-6">
	  <label for="empMjNm" class="form-label">매니저명</label>
	  <input type="hidden" name="empMjNum" class="form-control" id="empMjNum" />
	  <input type="text" class="form-control" id="empMjNm"
	  	placeholder="직원명을 입력해주세요" readonly />
	  <button type="button" class="btn btn-primary" id="btnEmpMjNum"
	  	 data-toggle="modal" data-target="#exampleModal"
	  >검색</button>
	</div>
	<!-- 매니저 등록 끝 -->
	<div class="col-12">
	  <button type="submit" class="btn btn-primary">등록</button>
	</div>
</form:form>
</div>
<div class="bd-example" id="manager" style="display:none;">
<form:form modelAttribute="empVO" action="/emp/createPost" method="post"
		 class="row g-3">
	<!-- 직원번호 시작 -->
	<div class="col-md-6" style="clear:both;">
	  <label for="empNum" class="form-label">직원번호</label>
<!-- 	  <input type="text" name="empNum" class="form-control" id="empNum" -->
<%-- 	  	value="${empNum}" placeholder="직원번호를 입력해주세요" /> --%>
<%-- 	  <form:input path="empNum" class="form-control" placeholder="직원번호를 입력해주세요" /> --%>
	  <input type="text" name="empNum" class="form-control" id="empNumAjax"
	  	value="" placeholder="직원번호를 입력해주세요" readonly />
	</div>
	<!-- 직원번호 끝 -->
	<!-- 주소 시작 -->
	<div class="col-md-2">
    	<label for="zipCode" class="form-label">우편번호</label>
    	<input type="text" name="zipCode" class="form-control" id="zipCode"
    		placeholder="우편번호를 검색해주세요" readonly />
    	<button type="button" class="btn btn-primary" id="btnPostno">검색</button>
	</div>
	<div class="col-12">
	    <label for="address" class="form-label">주소</label>
	    <input type="text" name="address" class="form-control" id="address" 
	    	placeholder="주소를 검색해주세요" readonly />
	</div>
	<div class="col-12">
	    <label for="detAddress" class="form-label">상세주소</label>
	    <input type="text" name="detAddress" class="form-control" id="detAddress" 
	    	placeholder="상세주소를 입력해주세요">
	</div>
    <!-- 주소 끝 -->
    <!-- 연락처 시작 -->
	<div class="col-md-6">
	  <label for="empPne" class="form-label">연락처</label>
	  <input type="text" name="empPne" class="form-control" id="empPne"
	  	placeholder="연락처를 입력해주세요" required />
	  <form:errors path="empPne" />
	</div>
	<!-- 연락처 끝 -->
    <!-- 직원명 시작 -->
	<div class="col-md-6">
	  <label for="empNm" class="form-label">직원명</label>
	  <input type="text" name="empNm" class="form-control" id="empNm"
	  	placeholder="직원명을 입력해주세요" required />
	  <form:errors path="empNm" />
	</div>
	<!-- 직원명 끝 -->
    <!-- 급여 시작 -->
	<div class="col-md-6">
	  <label for="empPay" class="form-label">급여</label>
	  <input type="number" name="empPay" class="form-control" id="empPay"
	  	placeholder="급여를 입력해주세요" required />
	  <form:errors path="empPay" />
	</div>
	<!-- 급여 끝 -->
	<!-- 매니저 등록 시작 -->
	<div class="col-md-6">
	  <label for="empMjNm" class="form-label">매니저명</label>
	  <input type="hidden" name="empMjNum" class="form-control" id="empMjNum" />
	  <input type="text" class="form-control" id="empMjNm"
	  	placeholder="직원명을 입력해주세요" readonly />
	  <button type="button" class="btn btn-primary" id="btnEmpMjNum"
	  	 data-toggle="modal" data-target="#exampleModal"
	  >검색</button>
	</div>
	<!-- 매니저 등록 끝 -->
	<div class="col-12">
	  <button type="submit" class="btn btn-primary">등록</button>
	</div>
</form:form>
</div>
<!-- Modal -->
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h1 class="modal-title fs-5" id="exampleModalLabel">Modal title</h1>
        <button type="button" class="btn-close" data-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        <!-- -------- 직원 목록 시작 ------------- -->
        <div class="bd-example">
		  <table class="table table-hover">
		      <thead>
		    <tr>
		      <th scope="col">#</th>
		      <th scope="col">직원번호</th>
		      <th scope="col">이름</th>
		    </tr>
		  </thead>
		  <tbody id="trAdd">
		    <tr>
		      <th scope="row">1</th>
		      <td>Mark</td>
		      <td>Otto</td>
		    </tr>
		  </tbody>
		  </table>
		</div>
        <!-- -------- 직원 목록 끝 ------------- -->
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
        <button type="button" class="btn btn-primary">Save changes</button>
      </div>
    </div>
  </div>
</div>

 

detail을 수정하자

  • c:forEach문 사용
  • scope
  • value="${employee.empNum } ... value에 값을 전부 셋팅
  • 관리자 input type hidden 을 text로 바꿈

<detail.jsp>

<%@ page language="java" contentType="text/html;charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<link rel="stylesheet" href="/resources/css/bootstrap.min.css" />
<script type="text/javascript" src="/resources/js/bootstrap.min.js"></script>
<script src="https://ssl.daumcdn.net/dmaps/map_js_init/postcode.v2.js"></script>
<script type="text/javascript" src="/resources/js/jquery-3.6.0.js"></script>
<script type="text/javascript">
$(function(){
	//다음 우편번호 검색
	$("#btnPostno").on("click",function(){
		new daum.Postcode({
			//다음 창에서 검색이 완료되면 콜백함수에 의해 결과 데이터가 data 객체로 들어옴
			oncomplete:function(data){
				//우편번호
				$("#zipCode").val(data.zonecode);
				$("#address").val(data.address);
				$("#detAddress").val(data.buildingName);
			}
		}).open();
	});
	
	
	//직원번호 자동등록
	// processType:false는 파일업로드 시 사용(let formData = new formData())
	// contentType:"application/json;charset:utf-8"(보내는 타입)
	// data:JSON.stringify(data);
	// type:"post"
	// success:function(){}
	$.ajax({
		url:"/emp/getEmpNum",
		type:"post",
		success:function(result){
			console.log("result : " + result);
			$("#empNumAjax").val(result);
		}
	});
	
	//매니저 선택하기
	$("#btnEmpMjNum").on("click",function(){
		$.ajax({
			url:"/emp/getEmpAll",
			type:"post",
			success:function(result){
				//result : List<EmpVO> empVOList
				let str = "";
				
				$.each(result,function(index, empVO){
					console.log("empVO.empNum : " + empVO.empNum);
					console.log("empVO.empNm : " + empVO.empNm);
					//<th scope="row"> : 해당 셀이 행(row)을 위한 헤더 셀임을 명시함.
					str += "<tr class='trSelect'><th scope='col'>"+(index+1)+"</th>";
					str += "<td>"+empVO.empNum+"</td><td>"+empVO.empNm+"</td></tr>";
				});
				
				console.log("str : " + str);
				//.html() : 새로고침 / .append() : 누적
				$("#trAdd").html(str);	//초기화
// 				$("#trAdd").append(str);
			}
		});
	});
	
	//동적으로 생성된 요소의 이벤트 처리
// 	달러(".trSelect").on("click",function(){})은 작동을 안할것임
	$(document).on("click",".trSelect",function(){
		//this : tr이 여러개인데 그 중 클릭한 바로 그 tr
		//td들을 가져옴. 그 안에 데이터를 가져와보자
		let resultStr = $(this).children().map(function(){
			return $(this).text();}).get().join(",");
		console.log("resultStr : " + resultStr);
		
		//resultStr : 5,EMP005,이정재 => split(",")을 해서 배열로 만들고
		//[1]는 매니저번호(empMjNum)로 입력, [2]는 매니저명(empMjNm)으로 입력
		//arr[0] : 5 / arr[1] : EMP005 / arr[2] : 이정재
		let arr = resultStr.split(",");
		$("#empMjNum").val(arr[1]);
		$("#empMjNm").val(arr[2]);
	});
	
	$(".nav-link").on("click",function(){
		//toggleClass() 메서드는 해당 클래스를 토글함
		$(".link").toggleClass("active");
		//removeAttr() : 선택한 요소에서 하나 이상의 특성을 제거함
		$(".link").removeAttr("aria-current");
		//attr() : 선택한 요소의 속성을 추가함
		$(this).attr("aria-current","page");
		//this : link 클래스는 2개. 그 중에서 클릭한 바로 그 요소
		let id = $(this).data("id");  //employee 또는 manager
		if(id=="employee"){ // 직원 탭의 경우 직원 div를 보여주고, 관리자 div는 hidden처리함
			$("#employee").css("display","block");
			$("#manager").css("display","none");
		}else{ //관리자의 탭의 경우 관리자 div를 보여주고, 직원 div는 hidden처리함
			$("#employee").css("display","none");
			$("#manager").css("display","block");
		}
	});
});
</script>
<!-- 요청URI : /emp/createPost
	요청파라미터 : {empNum=EMP001,zipCode=12345,address=대전...,empMjNum=}
	요청방식 : post
 -->
 <!-- data : List<EmpVO> empVOList 
 	stat.index : 0부터
 	stat.count : 1부터
 	
 	empVO : EmpVO(empNum=EMP006, empAddr=대전, empPne=010-, empNm=뷔, empPay=0, empMjNum=EMP006, serVOList=null)
	param : empNum=EMP006
	
	scope : page(동일 jsp), request(동일 요청), session(동일 웹브라우저), applicateion(웹브라우저)
	scope 기본은 page라  page일 경우 생략 가능
 -->
 
 <c:forEach var="empVO" items="${data}" varStatus="stat" > 
 	${empVO.empNum}, ${param.empNum}<br />
 	<c:choose>
 		<c:when test="${empVO.empNum==param.empNum}"> <!-- 직원 -->
 			<c:set var="employee" value="${empVO}" scope="page" />
 		</c:when>
 		<c:otherwise> <!-- 관리자 -->
 			<c:set var="manager" value="${empVO}"/>
 		</c:otherwise>
 	</c:choose>
 </c:forEach>
<ul class="nav nav-tabs">
  <li class="nav-item">
    <a class="nav-link link active" data-id="employee" aria-current="page" href="#">직원</a>
  </li>
  <li class="nav-item">
    <a class="nav-link link" data-id="manager" href="#">관리자</a>
  </li>
</ul>

<div class="bd-example" id="employee">
<form:form modelAttribute="empVO" action="/emp/createPost" method="post"
		 class="row g-3">
	<!-- 직원번호 시작 -->
	<div class="col-md-6" style="clear:both;">
	  <label for="empNum" class="form-label">직원번호</label>
<!-- 	  <input type="text" name="empNum" class="form-control" id="empNum" -->
<%-- 	  	value="${empNum}" placeholder="직원번호를 입력해주세요" /> --%>
<%-- 	  <form:input path="empNum" class="form-control" placeholder="직원번호를 입력해주세요" /> --%>
	  <input type="text" name="empNum" class="form-control" id="empNumAjax"
	  	value="${employee.empNum }" placeholder="직원번호를 입력해주세요" readonly />
	</div>
	<!-- 직원번호 끝 -->
	<!-- 주소 시작 -->
	<div class="col-md-2">
    	<label for="zipCode" class="form-label">우편번호</label>
    	<input type="text" name="zipCode" class="form-control" id="zipCode"
    		placeholder="우편번호를 검색해주세요" readonly />
    	<button type="button" class="btn btn-primary" id="btnPostno">검색</button>
	</div>
	<div class="col-12">
	    <label for="address" class="form-label">주소</label>
	    <input type="text" name="address" class="form-control" id="address" 
	    	placeholder="주소를 검색해주세요" readonly />
	</div>
	<div class="col-12">
	    <label for="detAddress" class="form-label">상세주소</label>
	    <input type="text" name="detAddress" class="form-control" id="detAddress" 
	    	placeholder="상세주소를 입력해주세요" value="${employee.empAddr}">
	</div>
    <!-- 주소 끝 -->
    <!-- 연락처 시작 -->
	<div class="col-md-6">
	  <label for="empPne" class="form-label">연락처</label>
	  <input type="text" name="empPne" class="form-control" id="empPne"
	  	placeholder="연락처를 입력해주세요" value="${employee.empPne}" required />
	  <form:errors path="empPne" />
	</div>
	<!-- 연락처 끝 -->
    <!-- 직원명 시작 -->
	<div class="col-md-6">
	  <label for="empNm" class="form-label">직원명</label>
	  <input type="text" name="empNm" class="form-control" id="empNm"
	  	placeholder="직원명을 입력해주세요" value="${employee.empNm}" required />
	  <form:errors path="empNm" />
	</div>
	<!-- 직원명 끝 -->
    <!-- 급여 시작 -->
	<div class="col-md-6">
	  <label for="empPay" class="form-label">급여</label>
	  <input type="number" name="empPay" class="form-control" id="empPay"
	  	placeholder="급여를 입력해주세요" value="${employee.empPay}" required />
	  <form:errors path="empPay" />
	</div>
	<!-- 급여 끝 -->
	<!-- 매니저 등록 시작 -->
	<div class="col-md-6">
	  <label for="empMjNm" class="form-label">매니저명</label>
	  <input type="text" name="empMjNum" class="form-control" 
	  id="empMjNum" value="${employee.empMjNum}" />
	  <input type="text" class="form-control" id="empMjNm"
	  	placeholder="직원명을 입력해주세요" readonly />
	  <button type="button" class="btn btn-primary" id="btnEmpMjNum"
	  	 data-toggle="modal" data-target="#exampleModal"
	  >검색</button>
	</div>
	<!-- 매니저 등록 끝 -->
	<div class="col-12">
	  <button type="submit" class="btn btn-primary">등록</button>
	</div>
</form:form>
</div>
<div class="bd-example" id="manager" style="display:none;">
<form:form modelAttribute="empVO" action="/emp/createPost" method="post"
		 class="row g-3">
	<!-- 직원번호 시작 -->
	<div class="col-md-6" style="clear:both;">
	  <label for="empNum" class="form-label">직원번호</label>
<!-- 	  <input type="text" name="empNum" class="form-control" id="empNum" -->
<%-- 	  	value="${empNum}" placeholder="직원번호를 입력해주세요" /> --%>
<%-- 	  <form:input path="empNum" class="form-control" placeholder="직원번호를 입력해주세요" /> --%>
	  <input type="text" name="empNum" value="${manager.empNum}" class="form-control" id="empNumAjax"
	  	value="" placeholder="직원번호를 입력해주세요" readonly />
	</div>
	<!-- 직원번호 끝 -->
	<!-- 주소 시작 -->
	<div class="col-md-2">
    	<label for="zipCode" class="form-label">우편번호</label>
    	<input type="text" name="zipCode" class="form-control" id="zipCode"
    		placeholder="우편번호를 검색해주세요" readonly />
    	<button type="button" class="btn btn-primary" id="btnPostno">검색</button>
	</div>
	<div class="col-12">
	    <label for="address" class="form-label">주소</label>
	    <input type="text" name="address" class="form-control" id="address" 
	    	placeholder="주소를 검색해주세요" readonly />
	</div>
	<div class="col-12">
	    <label for="detAddress" class="form-label">상세주소</label>
	    <input type="text" name="detAddress" class="form-control" id="detAddress" 
	    	placeholder="상세주소를 입력해주세요" value="${manager.empAddr}">
	</div>
    <!-- 주소 끝 -->
    <!-- 연락처 시작 -->
	<div class="col-md-6">
	  <label for="empPne" class="form-label">연락처</label>
	  <input type="text" name="empPne" class="form-control" id="empPne"
	  	placeholder="연락처를 입력해주세요" value="${manager.empPne}" required />
	  <form:errors path="empPne" />
	</div>
	<!-- 연락처 끝 -->
    <!-- 직원명 시작 -->
	<div class="col-md-6">
	  <label for="empNm" class="form-label">직원명</label>
	  <input type="text" name="empNm" class="form-control" id="empNm"
	  	placeholder="직원명을 입력해주세요" value="${manager.empNm}" required />
	  <form:errors path="empNm" />
	</div>
	<!-- 직원명 끝 -->
    <!-- 급여 시작 -->
	<div class="col-md-6">
	  <label for="empPay" class="form-label">급여</label>
	  <input type="number" name="empPay" class="form-control" id="empPay"
	  	placeholder="급여를 입력해주세요" value="${manager.empPay}" required />
	  <form:errors path="empPay" />
	</div>
	<!-- 급여 끝 -->
	<!-- 매니저 등록 시작 -->
	<div class="col-md-6">
	  <label for="empMjNm" class="form-label">매니저명</label>
	  <input type="hidden" name="empMjNum" class="form-control" 
	  id="empMjNum" value="${manager.empMjNum}" />
	  <input type="text" class="form-control" id="empMjNm"
	  	placeholder="직원명을 입력해주세요" readonly />
	  <button type="button" class="btn btn-primary" id="btnEmpMjNum"
	  	 data-toggle="modal" data-target="#exampleModal"
	  >검색</button>
	</div>
	<!-- 매니저 등록 끝 -->
	<div class="col-12">
	  <button type="submit" class="btn btn-primary">등록</button>
	</div>
</form:form>
</div>
<!-- Modal -->
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h1 class="modal-title fs-5" id="exampleModalLabel">Modal title</h1>
        <button type="button" class="btn-close" data-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        <!-- -------- 직원 목록 시작 ------------- -->
        <div class="bd-example">
		  <table class="table table-hover">
		      <thead>
		    <tr>
		      <th scope="col">#</th>
		      <th scope="col">직원번호</th>
		      <th scope="col">이름</th>
		    </tr>
		  </thead>
		  <tbody id="trAdd">
		    <tr>
		      <th scope="row">1</th>
		      <td>Mark</td>
		      <td>Otto</td>
		    </tr>
		  </tbody>
		  </table>
		</div>
        <!-- -------- 직원 목록 끝 ------------- -->
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
        <button type="button" class="btn btn-primary">Save changes</button>
      </div>
    </div>
  </div>
</div>

 

 

- 부트스트랩 가져오자

 

https://startbootstrap.com/previews/sb-admin-2

text-center 의 outer HTML로 소스 가져오자

 

그러고 div 밑에 붙혀넣기 

<c:if test="${manager!=null}"> 는 form태그를 감싸준다.

<div class="bd-example" id="manager" style="display:none;">
<c:if test="${manager==null}"> <!-- 이 직원은 매니저가 없음 -->
	<div class="text-center">
		<div class="error mx-auto" data-text="관리자가 없습니다." style="font-size:17px;">관리자가 없습니다. </div>
	</div>
</c:if>
<c:if test="${manager!=null}">

 


 

관리자가 없는 경우 출력 잘됨


 

sweetalert2 로 Toast 띄우자

 

  • <link rel="stylesheet" href="/resources/css/sweetalert2.min.css" />
  • <script type="text/javascript" src="/resources/js/sweetalert2.min.js"></script>

추가

 

 

<tiles -> index.jsp>

  • body에 class 를 주고
  • html 태그에도 class를 줌
<body id="page-top class="sidebar-mini sidebar-closed sidebar-collapse"">
<html class>

 

Toast를 써보자

<detail.jsp>

 

	$(".nav-link").on("click",function(){
		//toggleClass() 메서드는 해당 클래스를 토글함
		$(".link").toggleClass("active");
		//removeAttr() : 선택한 요소에서 하나 이상의 특성을 제거함
		$(".link").removeAttr("aria-current");
		//attr() : 선택한 요소의 속성을 추가함
		$(this).attr("aria-current","page");
		//this : link 클래스는 2개. 그 중에서 클릭한 바로 그 요소
		let id = $(this).data("id");  //employee 또는 manager
		if(id=="employee"){ // 직원 탭의 경우 직원 div를 보여주고, 관리자 div는 hidden처리함
			$("#employee").css("display","block");
			$("#manager").css("display","none");
		}else{ //관리자의 탭의 경우 관리자 div를 보여주고, 직원 div는 hidden처리함
			$("#employee").css("display","none");
			$("#manager").css("display","block");
		}
		
		Toast.fire({
			icon:'success',
			title:'새롬이'
		});
	});
	
	let Toast = Swal.mixin({
		toast:true,
		position:'top-end',
		showConfirmButton:false,
		timer:3000
	});

스크립트를 추가해주면

 

오른쪽 상단에 toast창이 뜬다.

 

  • readonly 처리
  • 등록버튼 수정 
  • 수정 모드 추가
  • 검색버튼 disabled

  • 스크립트 작성
	//수정버튼 클릭 -> spn1:none / spn2:block
	$("#edit").on("click",function(){
		$("#spn1").css("display","none");
		$("#spn2").css("display","block");
		//읽기전용 해제
		$(".form-control").removeAttr("readOnly");
		//검색버튼 사용
		$("#btnPostno").removeAttr("disabled");
		$("#btnEmpMjNum").removeAttr("disabled");
	});
	
	//취소버튼 클릭 -> spn1:block / spn2:none
	$("#cancel").on("click",function(){
		$("#spn1").css("display","block");
		$("#spn2").css("display","none");
		//읽기전용
		$(".form-control").attr("readOnly",true);
		//검색버튼 비활성
		$("#btnPostno").attr("disabled",true);
		$("#btnEmpMjNum").attr("disabled",true);
	});

 

수정버튼 눌렀을 때

 

검색버튼은 전부 disabled

 

<detail.jsp>

<%@ page language="java" contentType="text/html;charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<link rel="stylesheet" href="/resources/css/bootstrap.min.css" />
<link rel="stylesheet" href="/resources/css/sweetalert2.min.css" />
<script type="text/javascript" src="/resources/js/bootstrap.min.js"></script>
<script type="text/javascript" src="/resources/js/sweetalert2.min.js"></script>
<script src="https://ssl.daumcdn.net/dmaps/map_js_init/postcode.v2.js"></script>
<script type="text/javascript" src="/resources/js/jquery-3.6.0.js"></script>
<script type="text/javascript">
$(function(){
	//다음 우편번호 검색
	$("#btnPostno").on("click",function(){
		new daum.Postcode({
			//다음 창에서 검색이 완료되면 콜백함수에 의해 결과 데이터가 data 객체로 들어옴
			oncomplete:function(data){
				//우편번호
				$("#zipCode").val(data.zonecode);
				$("#address").val(data.address);
				$("#detAddress").val(data.buildingName);
			}
		}).open();
	});
	
	
	//직원번호 자동등록
	// processType:false는 파일업로드 시 사용(let formData = new formData())
	// contentType:"application/json;charset:utf-8"(보내는 타입)
	// data:JSON.stringify(data);
	// type:"post"
	// success:function(){}
	$.ajax({
		url:"/emp/getEmpNum",
		type:"post",
		success:function(result){
			console.log("result : " + result);
			$("#empNumAjax").val(result);
		}
	});
	
	//매니저 선택하기
	$("#btnEmpMjNum").on("click",function(){
		$.ajax({
			url:"/emp/getEmpAll",
			type:"post",
			success:function(result){
				//result : List<EmpVO> empVOList
				let str = "";
				
				$.each(result,function(index, empVO){
					console.log("empVO.empNum : " + empVO.empNum);
					console.log("empVO.empNm : " + empVO.empNm);
					//<th scope="row"> : 해당 셀이 행(row)을 위한 헤더 셀임을 명시함.
					str += "<tr class='trSelect'><th scope='col'>"+(index+1)+"</th>";
					str += "<td>"+empVO.empNum+"</td><td>"+empVO.empNm+"</td></tr>";
				});
				
				console.log("str : " + str);
				//.html() : 새로고침 / .append() : 누적
				$("#trAdd").html(str);	//초기화
// 				$("#trAdd").append(str);
			}
		});
	});
	
	//동적으로 생성된 요소의 이벤트 처리
// 	달러(".trSelect").on("click",function(){})은 작동을 안할것임
	$(document).on("click",".trSelect",function(){
		//this : tr이 여러개인데 그 중 클릭한 바로 그 tr
		//td들을 가져옴. 그 안에 데이터를 가져와보자
		let resultStr = $(this).children().map(function(){
			return $(this).text();}).get().join(",");
		console.log("resultStr : " + resultStr);
		
		//resultStr : 5,EMP005,이정재 => split(",")을 해서 배열로 만들고
		//[1]는 매니저번호(empMjNum)로 입력, [2]는 매니저명(empMjNm)으로 입력
		//arr[0] : 5 / arr[1] : EMP005 / arr[2] : 이정재
		let arr = resultStr.split(",");
		$("#empMjNum").val(arr[1]);
		$("#empMjNm").val(arr[2]);
	});
	
	$(".nav-link").on("click",function(){
		//toggleClass() 메서드는 해당 클래스를 토글함
		$(".link").toggleClass("active");
		//removeAttr() : 선택한 요소에서 하나 이상의 특성을 제거함
		$(".link").removeAttr("aria-current");
		//attr() : 선택한 요소의 속성을 추가함
		$(this).attr("aria-current","page");
		//this : link 클래스는 2개. 그 중에서 클릭한 바로 그 요소
		let id = $(this).data("id");  //employee 또는 manager
		if(id=="employee"){ // 직원 탭의 경우 직원 div를 보여주고, 관리자 div는 hidden처리함
			$("#employee").css("display","block");
			$("#manager").css("display","none");
		}else{ //관리자의 탭의 경우 관리자 div를 보여주고, 직원 div는 hidden처리함
			$("#employee").css("display","none");
			$("#manager").css("display","block");
		}
		
		Toast.fire({
			icon:'success',
			title:'새롬이'
		});
	});
	
	let Toast = Swal.mixin({
		toast:true,
		position:'top-end',
		showConfirmButton:false,
		timer:3000
	});
	
	//수정버튼 클릭 -> spn1:none / spn2:block
	$("#edit").on("click",function(){
		$("#spn1").css("display","none");
		$("#spn2").css("display","block");
		//읽기전용 해제
		$(".form-control").removeAttr("readOnly");
		//검색버튼 사용
		$("#btnPostno").removeAttr("disabled");
		$("#btnEmpMjNum").removeAttr("disabled");
	});
	
	//취소버튼 클릭 -> spn1:block / spn2:none
	$("#cancel").on("click",function(){
		$("#spn1").css("display","block");
		$("#spn2").css("display","none");
		//읽기전용
		$(".form-control").attr("readOnly",true);
		//검색버튼 비활성
		$("#btnPostno").attr("disabled",true);
		$("#btnEmpMjNum").attr("disabled",true);
	});
});
</script>
<!-- 요청URI : /emp/createPost
	요청파라미터 : {empNum=EMP001,zipCode=12345,address=대전...,empMjNum=}
	요청방식 : post
 -->
 <!-- data : List<EmpVO> empVOList 
 	stat.index : 0부터
 	stat.count : 1부터
 	
 	empVO : EmpVO(empNum=EMP006, empAddr=대전, empPne=010-, empNm=뷔, empPay=0, empMjNum=EMP006, serVOList=null)
	param : empNum=EMP006
	
	scope : page(동일 jsp), request(동일 요청), session(동일 웹브라우저), applicateion(웹브라우저)
	scope 기본은 page라  page일 경우 생략 가능
 -->
 
 <c:forEach var="empVO" items="${data}" varStatus="stat" > 
 	<c:choose>
 		<c:when test="${empVO.empNum==param.empNum}"> <!-- 직원 -->
 			<c:set var="employee" value="${empVO}" scope="page" />
 		</c:when>
 		<c:otherwise> <!-- 관리자 -->
 			<c:set var="manager" value="${empVO}"/>
 		</c:otherwise>
 	</c:choose>
 </c:forEach>
<ul class="nav nav-tabs">
  <li class="nav-item">
    <a class="nav-link link active" data-id="employee" aria-current="page" href="#">직원</a>
  </li>
  <li class="nav-item">
    <a class="nav-link link" data-id="manager" href="#">관리자</a>
  </li>
</ul>

<div class="bd-example" id="employee">
<form:form modelAttribute="empVO" action="/emp/createPost" method="post"
		 class="row g-3">
	<!-- 직원번호 시작 -->
	<div class="col-md-6" style="clear:both;">
	  <label for="empNum" class="form-label">직원번호</label>
<!-- 	  <input type="text" name="empNum" class="form-control" id="empNum" -->
<%-- 	  	value="${empNum}" placeholder="직원번호를 입력해주세요" /> --%>
<%-- 	  <form:input path="empNum" class="form-control" placeholder="직원번호를 입력해주세요" /> --%>
	  <input type="text" name="empNum" class="form-control" id="empNumAjax"
	  	value="${employee.empNum }" placeholder="직원번호를 입력해주세요" readonly />
	</div>
	<!-- 직원번호 끝 -->
	<!-- 주소 시작 -->
	<div class="col-md-2">
    	<label for="zipCode" class="form-label">우편번호</label>
    	<input type="text" name="zipCode" class="form-control" id="zipCode"
    		placeholder="우편번호를 검색해주세요" readonly />
    	<button type="button" class="btn btn-primary" id="btnPostno" disabled >검색</button>
	</div>
	<div class="col-12">
	    <label for="address" class="form-label">주소</label>
	    <input type="text" name="address" class="form-control" id="address" 
	    	placeholder="주소를 검색해주세요" readonly />
	</div>
	<div class="col-12">
	    <label for="detAddress" class="form-label">상세주소</label>
	    <input type="text" name="detAddress" class="form-control" id="detAddress" 
	    	placeholder="상세주소를 입력해주세요" value="${employee.empAddr}" readonly>
	</div>
    <!-- 주소 끝 -->
    <!-- 연락처 시작 -->
	<div class="col-md-6">
	  <label for="empPne" class="form-label">연락처</label>
	  <input type="text" name="empPne" class="form-control" id="empPne"
	  	placeholder="연락처를 입력해주세요" value="${employee.empPne}" required readonly />
	  <form:errors path="empPne" />
	</div>
	<!-- 연락처 끝 -->
    <!-- 직원명 시작 -->
	<div class="col-md-6">
	  <label for="empNm" class="form-label">직원명</label>
	  <input type="text" name="empNm" class="form-control" id="empNm"
	  	placeholder="직원명을 입력해주세요" value="${employee.empNm}" required readonly />
	  <form:errors path="empNm" />
	</div>
	<!-- 직원명 끝 -->
    <!-- 급여 시작 -->
	<div class="col-md-6">
	  <label for="empPay" class="form-label">급여</label>
	  <input type="number" name="empPay" class="form-control" id="empPay"
	  	placeholder="급여를 입력해주세요" value="${employee.empPay}" required readonly />
	  <form:errors path="empPay" />
	</div>
	<!-- 급여 끝 -->
	<!-- 매니저 등록 시작 -->
	<div class="col-md-6">
	  <label for="empMjNm" class="form-label">매니저명</label>
	  <input type="text" name="empMjNum" class="form-control" 
	  id="empMjNum" value="${employee.empMjNum}" />
	  <input type="text" class="form-control" id="empMjNm"
	  	placeholder="직원명을 입력해주세요" readonly />
	  <button type="button" class="btn btn-primary" id="btnEmpMjNum"
	  	 data-toggle="modal" data-target="#exampleModal" disabled
	  >검색</button>
	</div>
	<!-- 매니저 등록 끝 -->
	<div class="col-12">
		<!-- 일반모드 시작 -->
		<span id="spn1">
		  <button type="button" id="edit" class="btn btn-primary">수정</button>
		  <button type="button" id="delete" class="btn btn-danger">삭제</button>
		</span>
		<!-- 수정모드 시작 -->
		<span id="spn2" style="display:none;">
		  <button type="button" id="ok" class="btn btn-success">확인</button>
		  <button type="button" id="cancel" class="btn btn-warning">취소</button>
		</span>
	</div>
</form:form>
</div>
<div class="bd-example" id="manager" style="display:none;">
<c:if test="${manager==null}"> <!-- 이 직원은 매니저가 없음 -->
	<div class="text-center">
		<div class="error mx-auto" data-text="관리자가 없습니다." style="font-size:17px;">관리자가 없습니다. </div>
	</div>
</c:if>
<c:if test="${manager!=null}">
<form:form modelAttribute="empVO" action="/emp/createPost" method="post"
		 class="row g-3">
	<!-- 직원번호 시작 -->
	<div class="col-md-6" style="clear:both;">
	  <label for="empNum" class="form-label">직원번호</label>
<!-- 	  <input type="text" name="empNum" class="form-control" id="empNum" -->
<%-- 	  	value="${empNum}" placeholder="직원번호를 입력해주세요" /> --%>
<%-- 	  <form:input path="empNum" class="form-control" placeholder="직원번호를 입력해주세요" /> --%>
	  <input type="text" name="empNum" value="${manager.empNum}" class="form-control" id="empNumAjax"
	  	value="" placeholder="직원번호를 입력해주세요" readonly />
	</div>
	<!-- 직원번호 끝 -->
	<!-- 주소 시작 -->
	<div class="col-md-2">
    	<label for="zipCode" class="form-label">우편번호</label>
    	<input type="text" name="zipCode" class="form-control" id="zipCode"
    		placeholder="우편번호를 검색해주세요" readonly />
    	<button type="button" class="btn btn-primary" id="btnPostno">검색</button>
	</div>
	<div class="col-12">
	    <label for="address" class="form-label">주소</label>
	    <input type="text" name="address" class="form-control" id="address" 
	    	placeholder="주소를 검색해주세요" readonly />
	</div>
	<div class="col-12">
	    <label for="detAddress" class="form-label">상세주소</label>
	    <input type="text" name="detAddress" class="form-control" id="detAddress" 
	    	placeholder="상세주소를 입력해주세요" value="${manager.empAddr}">
	</div>
    <!-- 주소 끝 -->
    <!-- 연락처 시작 -->
	<div class="col-md-6">
	  <label for="empPne" class="form-label">연락처</label>
	  <input type="text" name="empPne" class="form-control" id="empPne"
	  	placeholder="연락처를 입력해주세요" value="${manager.empPne}" required />
	  <form:errors path="empPne" />
	</div>
	<!-- 연락처 끝 -->
    <!-- 직원명 시작 -->
	<div class="col-md-6">
	  <label for="empNm" class="form-label">직원명</label>
	  <input type="text" name="empNm" class="form-control" id="empNm"
	  	placeholder="직원명을 입력해주세요" value="${manager.empNm}" required />
	  <form:errors path="empNm" />
	</div>
	<!-- 직원명 끝 -->
    <!-- 급여 시작 -->
	<div class="col-md-6">
	  <label for="empPay" class="form-label">급여</label>
	  <input type="number" name="empPay" class="form-control" id="empPay"
	  	placeholder="급여를 입력해주세요" value="${manager.empPay}" required />
	  <form:errors path="empPay" />
	</div>
	<!-- 급여 끝 -->
	<!-- 매니저 등록 시작 -->
	<div class="col-md-6">
	  <label for="empMjNm" class="form-label">매니저명</label>
	  <input type="hidden" name="empMjNum" class="form-control" 
	  id="empMjNum" value="${manager.empMjNum}" />
	  <input type="text" class="form-control" id="empMjNm"
	  	placeholder="직원명을 입력해주세요" readonly />
	  <button type="button" class="btn btn-primary" id="btnEmpMjNum"
	  	 data-toggle="modal" data-target="#exampleModal"
	  >검색</button>
	</div>
	<!-- 매니저 등록 끝 -->
	<div class="col-12">
	  <button type="submit" class="btn btn-primary">등록</button>
	</div>
</form:form>
</c:if>
</div>
<!-- Modal -->
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h1 class="modal-title fs-5" id="exampleModalLabel">Modal title</h1>
        <button type="button" class="btn-close" data-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        <!-- -------- 직원 목록 시작 ------------- -->
        <div class="bd-example">
		  <table class="table table-hover">
		      <thead>
		    <tr>
		      <th scope="col">#</th>
		      <th scope="col">직원번호</th>
		      <th scope="col">이름</th>
		    </tr>
		  </thead>
		  <tbody id="trAdd">
		    <tr>
		      <th scope="row">1</th>
		      <td>Mark</td>
		      <td>Otto</td>
		    </tr>
		  </tbody>
		  </table>
		</div>
        <!-- -------- 직원 목록 끝 ------------- -->
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
        <button type="button" class="btn btn-primary">Save changes</button>
      </div>
    </div>
  </div>
</div>

 

 


Merge_Into

  • INSERT와 UPDATE를 동시에 처리

쿼리문 연습

MERGE INTO EMP A --대상 테이블
USING DUAL 
ON(A.EMP_NUM = 'EMP001') --조건절(주로 기본키 데이터)
WHEN MATCHED THEN --조건절에 해당하는 데이터가 있으면 실행
    UPDATE SET EMP_NM = '새롬이연습', EMP_ADDR = '안드로메다'
WHEN NOT MATCHED THEN --조건절에 해당하는 데이터가 없으면 실행
    INSERT (EMP_NUM, EMP_ADDR, EMP_PNE, EMP_NM, EMP_PAY, EMP_MJ_NUM)
    VALUES('EMP999','대전 중구','010-','강해린',12345,'')    
;

 

 

<emp_SQL.xml>

  • 신규 직원 등록 (createPost) 수정
	<!-- 신규 직원 등록 및 수정 처리 -->
   <insert id="createPost" parameterType="empVO">
      <selectKey resultType="String" order="AFTER" keyProperty="empNum">
         SELECT MAX(EMP_NUM)
         FROM   EMP
      </selectKey>
   
      MERGE INTO EMP A
      USING DUAL 
      ON(A.EMP_NUM = #{empNum})
      WHEN MATCHED THEN
          UPDATE SET EMP_ADDR = #{empAddr}, EMP_PNE=#{empPne},
                     EMP_NM = #{empNm}, EMP_PAY=#{empPay}, EMP_MJ_NUM=#{empMjNum}
      WHEN NOT MATCHED THEN
          INSERT(EMP_NUM, EMP_ADDR, EMP_PNE, EMP_NM, EMP_PAY, EMP_MJ_NUM)
          VALUES((
		             SELECT NVL(SUBSTR(MAX(EMP_NUM),1,3),'EMP')
		              || TRIM(TO_CHAR(NVL(SUBSTR(MAX(EMP_NUM),4),0) + 1,'000'))
		            FROM   EMP
		          )
          ,#{empAddr},#{empPne},#{empNm},#{empPay},#{empMjNum})
   </insert>

 

<detail.jsp>

  • <input type="text" name="mode" id="mode" value="update" /> 추가

 

<EmpController.java>

  • createPost 매서드 수정
  • 파라미터에 @RequestParam(required=false,defaultValue="new") String mode 추가
@PostMapping("/createPost")
	public String createPost(@Valid @ModelAttribute EmpVO empVO,
			String zipCode, String address, String detAddress,
			@RequestParam(required=false,defaultValue="new") String mode,
			Errors errors) {
		
		//mode
		//- create에서 오면 new
		//- detail에서 오면 update
		log.info("mode :" + mode);
		
		String oldEmpNum = "";
		
		// update를 실행한다면..
		if(mode.equals("update")) {
			oldEmpNum = empVO.getEmpNum(); // 기본키 데이터 백업
		}
		
		if(errors.hasErrors()) {
			//forwarding
			return "emp/create";
		}
		
		// 우편번호 + 주소 + 상세주소 => empVO의 enpAddr 멤버변수에 setting 하기
		String empAddr = zipCode + " " + address + " " + detAddress;
		
		empVO.setEmpAddr(empAddr);
		
		log.info("empVO :" + empVO);
		
		int result = this.empService.createPost(empVO);
		
		// mode가 update
		if(mode.equals("update")) {
			return "redirect:/emp/detail?empNum="+oldEmpNum;
		}else {
			// insert일 경우
			return "redirect:/emp/detail?empNum="+empVO.getEmpNum();
		}
	}

 

<detail.jsp>

  •   <button type="submit" id="ok" class="btn btn-success">확인</button>
  • 확인 버튼 타입을 submit으로 바꾼다.
  • 자동등록 부분 ajax 주석처리한다.

수정해보면 데이터가 바뀌는 걸 볼 수 있다 ~

 

 


delete

  • id="employeeEmpNum" 아이디 설정

 

  • 스크립트
// 삭제버튼 클릭
	$("#delete").on("click",function(){ 
		// 파라미터를 javascript 변수에 저장하고자 한다면..
		let empNumJs = "${param.empNum}"; // 이렇게는 안쓴다.(보안에 취약할 수 있음) 이 방식은 DB를 거쳐오지 않았음
		let empNum = $("#employeeEmpNum").val();
		
		//세션스토리지에 변수값을 넣고자 한다면..
		sessionStorage.setItem("empNum", empNum);
		
		console.log("empNumJs : " + empNumJs + ", empNum :" + empNum); 
		
		//true(1) / false(0)
		let cfm = confirm("삭제하시겠습니까?");
		console.log("cfm: " + cfm);
		
		if(cfm>0){ //삭제 수행
			//json 오브젝트
			let data = {"empNum":empNum};
			
			// contentType : 보내는 타입
			// dataType : 응답 데이터 타입
			$.ajax({
				url:"/emp/deletePost",
				contentType:"application/json;charset=utf-8",
				data:JSON.stringify(data),
				dataType:"json",
				type:"post",
				success:function(result){
					//controller에서  map.put("result",1); / ResponseBody
					console.log("result : "+ JSON.stringify(result));
					//result : {"result":"1"}
					let str = result.result;	//1 또는 0 
					
					//str이 0보다 크면 성공, 아니면 실패
					//성공 시 /emp/list로 이동/ 실패 시 실패 메시지를 보여줌
					if(str>0){
						location.href="list";
					}else{
						Toast.fire({
							icon:'success',
							title:'삭제가 실패되었습니다.'
						});
					}
				}
			});
		}else{ // 삭제 취소
			Toast.fire({
				icon:'success',
				title:'삭제가 취소되었습니다.'
			});
		}
	});

 

 

삭제취소 눌렀을 경우

 

<emp_SQL.xml>

	<!-- 직원 삭제 -->
	<delete id="deletePost" parameterType="empVO">
		DELETE FORM EMP
		WHERE EMP_NUM = #{empNum}
	</delete>

<EmpMapper.xml>

// 직원 삭제
	public int deletePost(EmpVO empVO);

 

 

<EmpService.java>

// 직원 삭제
	public int deletePost(EmpVO empVO);

 

<EmpServiceImpl.java>

	// 직원 삭제
	@Override
	public int deletePost(EmpVO empVO) {
		return this.empMapper.deletePost(empVO);
	}

 

<EmpController.java>

 

	/*
	요청 URI : /emp/deletePost
	요청파라미터 : let data = {"empNum":empNum}
	요청방식 : post
	*/
	@ResponseBody
	@PostMapping("/deletePost")
	public Map<String, String> deletePost(@RequestBody EmpVO empVO) {
		
		int result = this.empService.deletePost(empVO);
		
		Map<String, String> map = new HashMap<String, String>();
		map.put("result", result+"");
		
		log.info("map : " + map);
		
		return map; 
	}

 

 


LIST 목록 출력

 

<emp_SQL.xml>

	<!-- 직원 목록 -->
	<select id="list" resultType="empVO">
		SELECT EMP_NUM, EMP_ADDR, EMP_PNE, EMP_NM, EMP_PAY, EMP_MJ_NUM
		FROM EMP
		START WITH EMP_MJ_NUM IS NULL
		CONNECT BY PRIOR EMP_NUM = EMP_MJ_NUM
	</select>

 

<EmpMapper.java>

// 직원 목록
	public List<EmpVO> list();

 

<EmpService.java>

// 직원 목록
	public List<EmpVO> list();

 

<EmpServiceImpl.java>

	// 직원 목록
	@Override
	public List<EmpVO> list() {
		return this.empMapper.list();
	}

 

 

<EmpController.java>

	/*
	 요청URI : /emp/list
	 요청방식: get
	 */
	@GetMapping("/list")
	public String list(Model model){
		List<EmpVO> empVOList = this.empService.list();
		
		log.info("empVOList : " + empVOList);
		
		model.addAttribute("data", empVOList);
		//forwarding
		return "emp/list";
	}

 

 

- 테이블 부트스트랩 적용

https://startbootstrap.com/previews/sb-admin-2

 

<list.jsp>

  • 부트스트랩 수정 후
  • forEach문을 통해 리스트를 출력한다.
<%@ page language="java" contentType="text/html;charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<div class="card shadow mb-4">
	<div class="card-header py-3">
		<h6 class="m-0 font-weight-bold text-primary">직원목록</h6>
	</div>
	<div class="card-body">
		<div class="table-responsive">
			<div id="dataTable_wrapper" class="dataTables_wrapper dt-bootstrap4">
				<div class="row">
					<div class="col-sm-12 col-md-6">
						<div class="dataTables_length" id="dataTable_length">
							<label>Show <select name="dataTable_length"
								aria-controls="dataTable"
								class="custom-select custom-select-sm form-control form-control-sm"><option
										value="10">10</option>
									<option value="25">25</option>
									<option value="50">50</option>
									<option value="100">100</option></select> entries
							</label>
						</div>
					</div>
					<div class="col-sm-12 col-md-6">
						<div id="dataTable_filter" class="dataTables_filter">
							<label>Search:<input type="search"
								class="form-control form-control-sm" placeholder=""
								aria-controls="dataTable"></label>
						</div>
					</div>
				</div>
				<div class="row">
					<div class="col-sm-12">
						<table class="table table-bordered dataTable" id="dataTable"
							width="100%" cellspacing="0" role="grid"
							aria-describedby="dataTable_info" style="width: 100%;">
							<thead>
								<tr role="row">
									<th class="sorting sorting_asc" tabindex="0"
										aria-controls="dataTable" rowspan="1" colspan="1"
										aria-sort="ascending"
										aria-label="Name: activate to sort column descending"
										style="width: 66px;">번호</th>
									<th class="sorting" tabindex="0" aria-controls="dataTable"
										rowspan="1" colspan="1"
										aria-label="Position: activate to sort column ascending"
										style="width: 79px;">직원번호</th>
									<th class="sorting" tabindex="0" aria-controls="dataTable"
										rowspan="1" colspan="1"
										aria-label="Office: activate to sort column ascending"
										style="width: 54px;">직원명</th>
									<th class="sorting" tabindex="0" aria-controls="dataTable"
										rowspan="1" colspan="1"
										aria-label="Age: activate to sort column ascending"
										style="width: 31px;">급여</th>
									<th class="sorting" tabindex="0" aria-controls="dataTable"
										rowspan="1" colspan="1"
										aria-label="Start date: activate to sort column ascending"
										style="width: 69px;">매니저</th>
								</tr>
							</thead>
							<tbody>
								<c:forEach var="empVO" items="${data}" varStatus="stat">
								<tr class="odd">
									<td class="sorting_1">${stat.count}</td>
									<td>${empVO.empNum}</td>
									<td>${empVO.empNm}</td>
									<td>${empVO.empPay}</td>
									<td>${empVO.empMjNum}</td>
								</tr>
								</c:forEach>
							</tbody>
						</table>
					</div>
				</div>
				<div class="row">
					<div class="col-sm-12 col-md-5">
						<div class="dataTables_info" id="dataTable_info" role="status"
							aria-live="polite">Showing 1 to 10 of 57 entries</div>
					</div>
					<div class="col-sm-12 col-md-7">
						<div class="dataTables_paginate paging_simple_numbers"
							id="dataTable_paginate">
							<ul class="pagination">
								<li class="paginate_button page-item previous disabled"
									id="dataTable_previous"><a href="#"
									aria-controls="dataTable" data-dt-idx="0" tabindex="0"
									class="page-link">Previous</a></li>
								<li class="paginate_button page-item active"><a href="#"
									aria-controls="dataTable" data-dt-idx="1" tabindex="0"
									class="page-link">1</a></li>
								<li class="paginate_button page-item "><a href="#"
									aria-controls="dataTable" data-dt-idx="2" tabindex="0"
									class="page-link">2</a></li>
								<li class="paginate_button page-item "><a href="#"
									aria-controls="dataTable" data-dt-idx="3" tabindex="0"
									class="page-link">3</a></li>
								<li class="paginate_button page-item "><a href="#"
									aria-controls="dataTable" data-dt-idx="4" tabindex="0"
									class="page-link">4</a></li>
								<li class="paginate_button page-item "><a href="#"
									aria-controls="dataTable" data-dt-idx="5" tabindex="0"
									class="page-link">5</a></li>
								<li class="paginate_button page-item "><a href="#"
									aria-controls="dataTable" data-dt-idx="6" tabindex="0"
									class="page-link">6</a></li>
								<li class="paginate_button page-item next" id="dataTable_next"><a
									href="#" aria-controls="dataTable" data-dt-idx="7" tabindex="0"
									class="page-link">Next</a></li>
							</ul>
						</div>
					</div>
				</div>
			</div>
		</div>
	</div>
</div>

 

 

쿼리문

<emp_SQL.xml>

  • 직원 목록 수정
  • 매니저 번호가 아니라 매니저 이름이 출력되게 바꾸자

 

!-- 직원 목록 -->
	<select id="list" resultType="empVO">
		SELECT A.EMP_NUM, A.EMP_ADDR, A.EMP_PNE, A.EMP_NM, A.EMP_PAY
		     , A.EMP_MJ_NUM
		     , (SELECT B.EMP_NM FROM EMP B WHERE B.EMP_NUM = A.EMP_MJ_NUM) EMP_MJ_NM
		FROM   EMP A
		START WITH A.EMP_MJ_NUM IS NULL
		CONNECT BY PRIOR A.EMP_NUM = A.EMP_MJ_NUM
	</select>

 

매니저 번호와 매니저명을 같이 설정해야 모달창 띄울 때 오류가 안나므로

멤버변수 추가해준다.

 

<EmpVO.jav>

  • //매니저명(EMP_MJ_NM)
    private String empMjNm;
package kr.or.ddit.vo;

import java.util.List;

import javax.validation.constraints.NotNull;

import org.hibernate.validator.constraints.NotBlank;

import lombok.Data;

//직원
@Data
public class EmpVO {
	//직원 번호
	@NotBlank
	private String empNum;
	//주소
	private String empAddr;
	//연락처
	@NotBlank
	private String empPne;
	//직원 명
	@NotBlank
	private String empNm;
	//급여
	@NotNull
	private int empPay;
	//매니저 번호
	private String empMjNum;
	//매니저명(EMP_MJ_NM)
	private String empMjNm;
	//직원(EMP) : 서비스(SER) = 1 : N
	private List<SerVO> serVOList;

}

 

<list.jsp>

  • 모달 추가
<td data-bs-toggle="modal" data-bs-target="#exampleModal"> <a data-bs-toggle="modal" href="#exampleModal">${empVO.empMjNum}</a>

여기서 td에다가 모달과 같은 토글과 아이디값을 넣어주거나
a태그에 모달과 같은 토글값을 넣어주면 모달창이 실행 된다
둘 중 하나 써주면 됨
<%@ page language="java" contentType="text/html;charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<link rel="stylesheet" href="/resources/css/bootstrap.min.css" />
<link rel="stylesheet" href="/resources/css/sweetalert2.min.css" />
<script type="text/javascript" src="/resources/js/bootstrap.min.js"></script>
<script src="https://ssl.daumcdn.net/dmaps/map_js_init/postcode.v2.js"></script>
<script type="text/javascript" src="/resources/js/jquery-3.6.0.js"></script>
<script type="text/javascript" src="/resources/js/sweetalert2.min.js"></script>
<div class="card shadow mb-4">
	<div class="card-header py-3">
		<h6 class="m-0 font-weight-bold text-primary">직원목록</h6>
	</div>
	<div class="card-body">
		<div class="table-responsive">
			<div id="dataTable_wrapper" class="dataTables_wrapper dt-bootstrap4">
				<div class="row">
					<div class="col-sm-12 col-md-6">
						<div class="dataTables_length" id="dataTable_length">
							<label>Show <select name="dataTable_length"
								aria-controls="dataTable"
								class="custom-select custom-select-sm form-control form-control-sm"><option
										value="10">10</option>
									<option value="25">25</option>
									<option value="50">50</option>
									<option value="100">100</option></select> entries
							</label>
						</div>
					</div>
					<div class="col-sm-12 col-md-6">
						<div id="dataTable_filter" class="dataTables_filter">
							<label>Search:<input type="search"
								class="form-control form-control-sm" placeholder=""
								aria-controls="dataTable"></label>
						</div>
					</div>
				</div>
				<div class="row">
					<div class="col-sm-12">
						<table class="table table-bordered dataTable" id="dataTable"
							width="100%" cellspacing="0" role="grid"
							aria-describedby="dataTable_info" style="width: 100%;">
							<thead>
								<tr role="row">
									<th class="sorting sorting_asc" tabindex="0"
										aria-controls="dataTable" rowspan="1" colspan="1"
										aria-sort="ascending"
										aria-label="Name: activate to sort column descending"
										style="width: 66px;">번호</th>
									<th class="sorting" tabindex="0" aria-controls="dataTable"
										rowspan="1" colspan="1"
										aria-label="Position: activate to sort column ascending"
										style="width: 79px;">직원번호</th>
									<th class="sorting" tabindex="0" aria-controls="dataTable"
										rowspan="1" colspan="1"
										aria-label="Office: activate to sort column ascending"
										style="width: 54px;">직원명</th>
									<th class="sorting" tabindex="0" aria-controls="dataTable"
										rowspan="1" colspan="1"
										aria-label="Age: activate to sort column ascending"
										style="width: 31px;">급여</th>
									<th class="sorting" tabindex="0" aria-controls="dataTable"
										rowspan="1" colspan="1"
										aria-label="Start date: activate to sort column ascending"
										style="width: 69px;">매니저</th>
								</tr>
							</thead>
							<tbody>
								<!-- data : List<EmpVO> empVOList 
									empVO : EmpVO
								stat.index : 0부터 시작
								stat.count : 1부터 시작
								-->
								<c:forEach var="empVO" items="${data}" varStatus="stat">
								<tr class="odd">
									<td class="sorting_1">${stat.count}</td>
									<td>${empVO.empNum}</td>
									<td>${empVO.empNm}</td>
									<td>${empVO.empPay}</td>
									<td data-bs-toggle="modal" data-bs-target="#exampleModal">
										<a class="showMj" data-empMjNum="${empVO.empMjNum}" 
										data-bs-toggle="modal" href="#exampleModal">${empVO.empMjNm}</a>
									</td>
								</tr>
								</c:forEach>
							</tbody>
						</table>
					</div>
				</div>
				<div class="row">
					<div class="col-sm-12 col-md-5">
						<div class="dataTables_info" id="dataTable_info" role="status"
							aria-live="polite">Showing 1 to 10 of 57 entries</div>
					</div>
					<div class="col-sm-12 col-md-7">
						<div class="dataTables_paginate paging_simple_numbers"
							id="dataTable_paginate">
							<ul class="pagination">
								<li class="paginate_button page-item previous disabled"
									id="dataTable_previous"><a href="#"
									aria-controls="dataTable" data-dt-idx="0" tabindex="0"
									class="page-link">Previous</a></li>
								<li class="paginate_button page-item active"><a href="#"
									aria-controls="dataTable" data-dt-idx="1" tabindex="0"
									class="page-link">1</a></li>
								<li class="paginate_button page-item "><a href="#"
									aria-controls="dataTable" data-dt-idx="2" tabindex="0"
									class="page-link">2</a></li>
								<li class="paginate_button page-item "><a href="#"
									aria-controls="dataTable" data-dt-idx="3" tabindex="0"
									class="page-link">3</a></li>
								<li class="paginate_button page-item "><a href="#"
									aria-controls="dataTable" data-dt-idx="4" tabindex="0"
									class="page-link">4</a></li>
								<li class="paginate_button page-item "><a href="#"
									aria-controls="dataTable" data-dt-idx="5" tabindex="0"
									class="page-link">5</a></li>
								<li class="paginate_button page-item "><a href="#"
									aria-controls="dataTable" data-dt-idx="6" tabindex="0"
									class="page-link">6</a></li>
								<li class="paginate_button page-item next" id="dataTable_next"><a
									href="#" aria-controls="dataTable" data-dt-idx="7" tabindex="0"
									class="page-link">Next</a></li>
							</ul>
						</div>
					</div>
				</div>
			</div>
		</div>
	</div>
</div>
<!-- Modal -->
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h1 class="modal-title fs-5" id="exampleModalLabel">매니저정보</h1>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        <!-- 내용 시작 -->
         <div class="mb-3 row">
		    <label for="staticEmail" class="col-sm-2 col-form-label">직원 번호</label>
		    <div class="col-sm-10">
		      <input type="text" readonly class="form-control-plaintext" id="empNum" value="">
		    </div>
		  </div>
         <div class="mb-3 row">
		    <label for="staticEmail" class="col-sm-2 col-form-label">직원 명</label>
		    <div class="col-sm-10">
		      <input type="text" readonly class="form-control-plaintext" id="empNm" value="">
		    </div>
		  </div>
         <div class="mb-3 row">
		    <label for="staticEmail" class="col-sm-2 col-form-label">연락처</label>
		    <div class="col-sm-10">
		      <input type="text" readonly class="form-control-plaintext" id="empPne" value="">
		    </div>
		  </div>
         <div class="mb-3 row">
		    <label for="staticEmail" class="col-sm-2 col-form-label">주소</label>
		    <div class="col-sm-10">
		      <input type="text" readonly class="form-control-plaintext" id="empAddr" value="">
		    </div>
		  </div>
         <div class="mb-3 row">
		    <label for="staticEmail" class="col-sm-2 col-form-label">급여</label>
		    <div class="col-sm-10">
		      <input type="text" readonly class="form-control-plaintext" id="empPay" value="">
		    </div>
		  </div>
         <div class="mb-3 row">
		    <label for="staticEmail" class="col-sm-2 col-form-label">매니저</label>
		    <div class="col-sm-10">
		      <input type="text" readonly class="form-control-plaintext" id="empMjNm" value="">
		    </div>
		  </div>
        <!-- 내용 끝 -->
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
      </div>
    </div>
  </div>
</div>
<script type="text/javascript">
$(function(){
	$(document).on("click",".showMj",function(){
// 	$("#showMj").on("click",function(){
		console.log("ajax로 매니저 정보 가져와보자");
		console.log("요청URI : /emp/showMj");
		console.log("요청파라미터(json) : {'empNum':'EMP006'}");
		console.log("요청방식 : post");
	});
});
</script>


이제 모달창에 리스트 출력 되게 해보자

 

-부트스트랩

https://getbootstrap.com/docs/5.3/forms/form-control/

 

Form controls

Give textual form controls like <input>s and <textarea>s an upgrade with custom styles, sizing, focus states, and more.

getbootstrap.com

 

  <div class="mb-3 row">
    <label for="staticEmail" class="col-sm-2 col-form-label">Email</label>
    <div class="col-sm-10">
      <input type="text" readonly class="form-control-plaintext" id="staticEmail" value="email@example.com">
    </div>
  </div>
  <div class="mb-3 row">
    <label for="inputPassword" class="col-sm-2 col-form-label">Password</label>
    <div class="col-sm-10">
      <input type="password" class="form-control" id="inputPassword">
    </div>
  </div>

 

<list.jsp>

  • 스크립트 추가
<script type="text/javascript">
$(function(){
// 	$(document).on("click",".showMj",function(){
	$(".showMj").on("click",function(){
		console.log("ajax로 매니저 정보 가져와보자");
		console.log("요청URI : /emp/showMj");
		console.log("요청파라미터(json) : {'empNum':'EMP006'}");
		console.log("요청방식 : post");
		//this : class="showMj"이 여러개이고, 이 중에서 하나를 클릭한 바로 그 요소
		//data-emp-mj-num="EMP006"
		let empMjNum = $(this).data("empMjNum");
		console.log("empMjNum : " + empMjNum);
		
		//json object
		let data = {"empMjNum":empMjNum};
		
		$.ajax({
			url:"/emp/showMj",
			contentType:"application/json;charset:utf-8",
			data:JSON.stringify(data),//마샬링,일렬화(serialization)
			type:"post",
			dataType:"json",
			success:function(result){
				console.log("result : " + JSON.stringify(result));
				
				$("#empNum").val(result.empNum);
				$("#empNm").val(result.empNm);
				$("#empPne").val(result.empPne);
				$("#empAddr").val(result.empAddr);
				$("#empPay").val(result.empPay);
				$("#empMjNm").val(result.empMjNm);
			}
		});
	});
});
</script>

<%@ page language="java" contentType="text/html;charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<link rel="stylesheet" href="/resources/css/bootstrap.min.css" />
<link rel="stylesheet" href="/resources/css/sweetalert2.min.css" />
<script type="text/javascript" src="/resources/js/bootstrap.min.js"></script>
<script src="https://ssl.daumcdn.net/dmaps/map_js_init/postcode.v2.js"></script>
<script type="text/javascript" src="/resources/js/jquery-3.6.0.js"></script>
<script type="text/javascript" src="/resources/js/sweetalert2.min.js"></script>
<div class="card shadow mb-4">
	<div class="card-header py-3">
		<h6 class="m-0 font-weight-bold text-primary">직원목록</h6>
	</div>
	<div class="card-body">
		<div class="table-responsive">
			<div id="dataTable_wrapper" class="dataTables_wrapper dt-bootstrap4">
				<div class="row">
					<div class="col-sm-12 col-md-6">
						<div class="dataTables_length" id="dataTable_length">
							<label>Show <select name="dataTable_length"
								aria-controls="dataTable"
								class="custom-select custom-select-sm form-control form-control-sm"><option
										value="10">10</option>
									<option value="25">25</option>
									<option value="50">50</option>
									<option value="100">100</option></select> entries
							</label>
						</div>
					</div>
					<div class="col-sm-12 col-md-6">
						<div id="dataTable_filter" class="dataTables_filter">
							<label>Search:<input type="search"
								class="form-control form-control-sm" placeholder=""
								aria-controls="dataTable"></label>
						</div>
					</div>
				</div>
				<div class="row">
					<div class="col-sm-12">
						<table class="table table-bordered dataTable" id="dataTable"
							width="100%" cellspacing="0" role="grid"
							aria-describedby="dataTable_info" style="width: 100%;">
							<thead>
								<tr role="row">
									<th class="sorting sorting_asc" tabindex="0"
										aria-controls="dataTable" rowspan="1" colspan="1"
										aria-sort="ascending"
										aria-label="Name: activate to sort column descending"
										style="width: 66px;">번호</th>
									<th class="sorting" tabindex="0" aria-controls="dataTable"
										rowspan="1" colspan="1"
										aria-label="Position: activate to sort column ascending"
										style="width: 79px;">직원번호</th>
									<th class="sorting" tabindex="0" aria-controls="dataTable"
										rowspan="1" colspan="1"
										aria-label="Office: activate to sort column ascending"
										style="width: 54px;">직원명</th>
									<th class="sorting" tabindex="0" aria-controls="dataTable"
										rowspan="1" colspan="1"
										aria-label="Age: activate to sort column ascending"
										style="width: 31px;">급여</th>
									<th class="sorting" tabindex="0" aria-controls="dataTable"
										rowspan="1" colspan="1"
										aria-label="Start date: activate to sort column ascending"
										style="width: 69px;">매니저</th>
								</tr>
							</thead>
							<tbody>
								<!-- data : List<EmpVO> empVOList 
									empVO : EmpVO
								stat.index : 0부터 시작
								stat.count : 1부터 시작
								-->
								<c:forEach var="empVO" items="${data}" varStatus="stat">
								<tr class="odd">
									<td class="sorting_1">${stat.count}</td>
									<td>${empVO.empNum}</td>
									<td>${empVO.empNm}</td>
									<td>${empVO.empPay}</td>
									<td data-bs-toggle="modal" data-bs-target="#exampleModal">
										<a class="showMj" data-emp-mj-num="${empVO.empMjNum}" 
										data-bs-toggle="modal" href="#exampleModal">${empVO.empMjNm}</a>
									</td>
								</tr>
								</c:forEach>
							</tbody>
						</table>
					</div>
				</div>
				<div class="row">
					<div class="col-sm-12 col-md-5">
						<div class="dataTables_info" id="dataTable_info" role="status"
							aria-live="polite">Showing 1 to 10 of 57 entries</div>
					</div>
					<div class="col-sm-12 col-md-7">
						<div class="dataTables_paginate paging_simple_numbers"
							id="dataTable_paginate">
							<ul class="pagination">
								<li class="paginate_button page-item previous disabled"
									id="dataTable_previous"><a href="#"
									aria-controls="dataTable" data-dt-idx="0" tabindex="0"
									class="page-link">Previous</a></li>
								<li class="paginate_button page-item active"><a href="#"
									aria-controls="dataTable" data-dt-idx="1" tabindex="0"
									class="page-link">1</a></li>
								<li class="paginate_button page-item "><a href="#"
									aria-controls="dataTable" data-dt-idx="2" tabindex="0"
									class="page-link">2</a></li>
								<li class="paginate_button page-item "><a href="#"
									aria-controls="dataTable" data-dt-idx="3" tabindex="0"
									class="page-link">3</a></li>
								<li class="paginate_button page-item "><a href="#"
									aria-controls="dataTable" data-dt-idx="4" tabindex="0"
									class="page-link">4</a></li>
								<li class="paginate_button page-item "><a href="#"
									aria-controls="dataTable" data-dt-idx="5" tabindex="0"
									class="page-link">5</a></li>
								<li class="paginate_button page-item "><a href="#"
									aria-controls="dataTable" data-dt-idx="6" tabindex="0"
									class="page-link">6</a></li>
								<li class="paginate_button page-item next" id="dataTable_next"><a
									href="#" aria-controls="dataTable" data-dt-idx="7" tabindex="0"
									class="page-link">Next</a></li>
							</ul>
						</div>
					</div>
				</div>
			</div>
		</div>
	</div>
</div>
<!-- Modal -->
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h1 class="modal-title fs-5" id="exampleModalLabel">매니저정보</h1>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        <!-- 내용 시작 -->
         <div class="mb-3 row">
		    <label for="staticEmail" class="col-sm-2 col-form-label">직원 번호</label>
		    <div class="col-sm-10">
		      <input type="text" readonly class="form-control-plaintext" id="empNum" value="">
		    </div>
		  </div>
         <div class="mb-3 row">
		    <label for="staticEmail" class="col-sm-2 col-form-label">직원 명</label>
		    <div class="col-sm-10">
		      <input type="text" readonly class="form-control-plaintext" id="empNm" value="">
		    </div>
		  </div>
         <div class="mb-3 row">
		    <label for="staticEmail" class="col-sm-2 col-form-label">연락처</label>
		    <div class="col-sm-10">
		      <input type="text" readonly class="form-control-plaintext" id="empPne" value="">
		    </div>
		  </div>
         <div class="mb-3 row">
		    <label for="staticEmail" class="col-sm-2 col-form-label">주소</label>
		    <div class="col-sm-10">
		      <input type="text" readonly class="form-control-plaintext" id="empAddr" value="">
		    </div>
		  </div>
         <div class="mb-3 row">
		    <label for="staticEmail" class="col-sm-2 col-form-label">급여</label>
		    <div class="col-sm-10">
		      <input type="text" readonly class="form-control-plaintext" id="empPay" value="">
		    </div>
		  </div>
         <div class="mb-3 row">
		    <label for="staticEmail" class="col-sm-2 col-form-label">매니저</label>
		    <div class="col-sm-10">
		      <input type="text" readonly class="form-control-plaintext" id="empMjNm" value="">
		    </div>
		  </div>
        <!-- 내용 끝 -->
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
      </div>
    </div>
  </div>
</div>
<script type="text/javascript">
$(function(){
// 	$(document).on("click",".showMj",function(){
	$(".showMj").on("click",function(){
		console.log("ajax로 매니저 정보 가져와보자");
		console.log("요청URI : /emp/showMj");
		console.log("요청파라미터(json) : {'empNum':'EMP006'}");
		console.log("요청방식 : post");
		//this : class="showMj"이 여러개이고, 이 중에서 하나를 클릭한 바로 그 요소
		//data-emp-mj-num="EMP006"
		let empMjNum = $(this).data("empMjNum");
		console.log("empMjNum : " + empMjNum);
		
		//json object
		let data = {"empMjNum":empMjNum};
		
		$.ajax({
			url:"/emp/showMj",
			contentType:"application/json;charset:utf-8",
			data:JSON.stringify(data),//마샬링,일렬화(serialization)
			type:"post",
			dataType:"json",
			success:function(result){
				console.log("result : " + JSON.stringify(result));
				
				$("#empNum").val(result.empNum);
				$("#empNm").val(result.empNm);
				$("#empPne").val(result.empPne);
				$("#empAddr").val(result.empAddr);
				$("#empPay").val(result.empPay);
				$("#empMjNm").val(result.empMjNm);
			}
		});
	});
});
</script>

 

 

<emp_SQL.xml>

  • showMj 쿼리문 추가
<!-- 직원 1명의 정보 리턴
	empVO{empNum=0,empMjNum=EMP006,...}
	 -->
	<select id="showMj" parameterType="empVO" resultType="empVO">
		SELECT A.EMP_NUM, A.EMP_ADDR, A.EMP_PNE, A.EMP_NM, A.EMP_PAY, A.EMP_MJ_NUM
			, (SELECT B.EMP_NM FROM EMP B WHERE B.EMP_NUM = A.EMP_MJ_NUM) EMP_MJ_NM
		FROM   EMP A
		WHERE  A.EMP_NUM = #{empMjNum}
	</select>

 

<EmpMapper.java>

// 직원 1명의 정보를 리턴
	public EmpVO showMj(EmpVO empVO);

 

<EmpService.java>

// 직원 1명의 정보를 리턴
	public EmpVO showMj(EmpVO empVO);

 

<EmpServiceImpl.java>

	// 직원 1명의 정보를 리턴
	@Override
	public EmpVO showMj(EmpVO empVO) {
		// TODO Auto-generated method stub
		return this.empMapper.showMj(empVO);
	}

 

<EmpController.java>

  • showMj 매서드
	/** 직원 1명의 정보를 리턴
	 요청URI : /emp/showMj
	 요청파라미터 : let data = {"empMjNum":empMjNum};
	 요청방식 : post
	 응답데이터타입 : json
	 */
	@ResponseBody
	@PostMapping("/showMj")
	public EmpVO showMj(@RequestBody EmpVO empVO) {
		log.info("empVO : " + empVO);
		
		empVO = this.empService.showMj(empVO);
		log.info("empVO : " + empVO);
		
		return empVO;
	}

 

 

<list.jsp>

  • 직원번호 클릭시 상세보기 페이지

<detail.jsp>

  • a태그에 클래스를 버튼 클래스로 주면 버튼모양의 a태그가 걸린다.


검색

  • 우선 list 매서드를 수정 (파라미터에 map을 추가해준다,)

<EmpController.java>

/*
	 요청URI : /emp/list
	 요청방식: get
	 
	 map은 RequestParam
	 vo는 ModelAttribute
	 json은 RequestBody
	 
	 */
	@GetMapping("/list")
	public String list(Model model
			, @RequestParam Map<String, String> map){
		
		//map으로 파라미터를 받아서 매퍼xml에서 검색 조건으로 사용
		List<EmpVO> empVOList = this.empService.list(map);
		
		log.info("empVOList : " + empVOList);
		
		model.addAttribute("data", empVOList);
		//forwarding
		return "emp/list";
	}

<emp.SQL_xml>

		<!-- 직원 목록 
	드루와 : map{show=10,keyword=개똥이}
	LIKE와 함게 사용한 퍼센트(여러글자), 언더바(한글자)를 와일드카드라고 함 
	-->
	<select id="list" parameterType="hashMap" resultType="empVO">
		WITH T AS(
		    SELECT A.EMP_NUM, A.EMP_ADDR, A.EMP_PNE, A.EMP_NM, A.EMP_PAY
		         , A.EMP_MJ_NUM
		         , (SELECT B.EMP_NM FROM EMP B WHERE B.EMP_NUM = A.EMP_MJ_NUM) EMP_MJ_NM
		    FROM   EMP A
		    START WITH A.EMP_MJ_NUM IS NULL
		    CONNECT BY PRIOR A.EMP_NUM = A.EMP_MJ_NUM
		)
		SELECT *
		FROM   T
		WHERE  1 = 1
		<!-- 조건 검색 -->
		<if test="keyword!=null and keyword!=''">
		AND    (T.EMP_NUM 	LIKE '%' || #{keyword} || '%'
		OR     T.EMP_NM 	LIKE '%' || #{keyword} || '%'
		OR     T.EMP_MJ_NUM LIKE '%' || #{keyword} || '%')
		</if>
	</select>

 

<EmpMapper.java>

	// 직원 목록
	public List<EmpVO> list(Map<String, String> map);

 

<EmpService.java>

	// 직원 목록
	public List<EmpVO> list(Map<String, String> map);

 

<EmpServiceImpl.java>

 

// 직원 목록
	@Override
	public List<EmpVO> list(Map<String,String> map) {
		return this.empMapper.list(map);
	}

 

 

 


페이징

<emp_SQL_xml>

  • 겹치는 부분을 sql 태그로 빼줌
  • getTotal
<?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">
<!-- namespace : xml파일이 여러개일 수 있으므로
	이를 구별하기 위한 식별 용도로 사용
 -->
<mapper namespace="kr.or.ddit.mapper.EmpMapper">
	<sql id="where">
		<!-- 조건 검색 -->
		<if test="keyword!=null and keyword!=''">
		AND    (T.EMP_NUM   LIKE '%' || #{keyword} || '%'
		OR     T.EMP_NM 	LIKE '%' || #{keyword} || '%'
		OR     T.EMP_MJ_NUM LIKE '%' || #{keyword} || '%')
		</if>
	</sql>
	
	<!-- 다음 직원번호를 가져옴 -->
	<select id="getEmpNum" resultType="String">
		SELECT NVL(SUBSTR(MAX(EMP_NUM),1,3),'EMP')
		     || TRIM(TO_CHAR(NVL(SUBSTR(MAX(EMP_NUM),4),0) + 1,'000'))
		FROM   EMP
	</select>
	
	<!-- 신규 직원 등록 및 수정 처리 -->
	<insert id="createPost" parameterType="empVO">
		<selectKey resultType="String" order="AFTER" keyProperty="empNum">
			SELECT MAX(EMP_NUM)
			FROM   EMP
		</selectKey>
	
		MERGE INTO EMP A
		USING DUAL 
		ON(A.EMP_NUM = #{empNum})
		WHEN MATCHED THEN
		    UPDATE SET EMP_ADDR = #{empAddr}, EMP_PNE=#{empPne},
		               EMP_NM = #{empNm}, EMP_PAY=#{empPay}, EMP_MJ_NUM=#{empMjNum}
		WHEN NOT MATCHED THEN
		    INSERT(EMP_NUM, EMP_ADDR, EMP_PNE, EMP_NM, EMP_PAY, EMP_MJ_NUM)
		    VALUES((
		    	SELECT NVL(SUBSTR(MAX(EMP_NUM),1,3),'EMP')
			     || TRIM(TO_CHAR(NVL(SUBSTR(MAX(EMP_NUM),4),0) + 1,'000'))
				FROM   EMP
		    )
		    ,#{empAddr},#{empPne},#{empNm},#{empPay},#{empMjNum})
	</insert>
	
	<!-- 모든 직원 정보 가져오기 -->
	<select id="getEmpAll" resultType="empVO">
		SELECT EMP_NUM, EMP_ADDR, EMP_PNE, EMP_NM, EMP_PAY, EMP_MJ_NUM
		FROM   EMP
		ORDER BY EMP_NUM
	</select>
	
	<!-- 직원 상세 보기(관리자가 있으면 관리자 정보도 포함) 	-->
	<select id="detail" parameterType="empVO" resultType="empVO">
		SELECT A.EMP_NUM, A.EMP_ADDR, A.EMP_PNE, A.EMP_NM, A.EMP_PAY, A.EMP_MJ_NUM
		FROM   EMP A
		WHERE  A.EMP_NUM = #{empNum}
		OR     A.EMP_NUM = (
		        SELECT B.EMP_MJ_NUM FROM EMP B WHERE B.EMP_NUM = #{empNum}
		    )
	</select>
	
	<!-- 직원 삭제 
	empVO : {empNum=EMP001,zipCode=null,address=null...,empMjNum=null}
	-->
	<delete id="deletePost" parameterType="empVO">
		DELETE FROM EMP
		WHERE  EMP_NUM = #{empNum}
	</delete>
	
	<!-- 직원 목록 
	LIKE와 함게 사용한 퍼센트(여러글자), 언더바(한글자)를 와일드카드라고 함 
	-->
	<select id="list" parameterType="hashMap" resultType="empVO">
		WITH T AS(
		    SELECT A.EMP_NUM, A.EMP_ADDR, A.EMP_PNE, A.EMP_NM, A.EMP_PAY
		         , A.EMP_MJ_NUM
		         , (SELECT B.EMP_NM FROM EMP B WHERE B.EMP_NUM = A.EMP_MJ_NUM) EMP_MJ_NM
		    FROM   EMP A
		    START WITH A.EMP_MJ_NUM IS NULL
		    CONNECT BY PRIOR A.EMP_NUM = A.EMP_MJ_NUM
		)
		SELECT *
		FROM   T
		WHERE  1 = 1
		<include refid="where"></include>
	</select>
	
	<!-- 직원 1명의 정보 리턴 
	empVO{empNum=0,empMjNum=EMP006,..
	-->
	<select id="showMj" parameterType="empVO" resultType="empVO">
		SELECT A.EMP_NUM, A.EMP_ADDR, A.EMP_PNE, A.EMP_NM, A.EMP_PAY, A.EMP_MJ_NUM
			, (SELECT B.EMP_NM FROM EMP B WHERE B.EMP_NUM = A.EMP_MJ_NUM) EMP_MJ_NM
		FROM   EMP A
		WHERE  A.EMP_NUM = #{empMjNum}
	</select>
	
	<!-- 목록의 행 수를 구함 -->
	<select id="getTotal" parameterType="hashMap" resultType="int">
		WITH T AS(
		    SELECT A.EMP_NUM, A.EMP_ADDR, A.EMP_PNE, A.EMP_NM, A.EMP_PAY
		         , A.EMP_MJ_NUM
		         , (SELECT B.EMP_NM FROM EMP B WHERE B.EMP_NUM = A.EMP_MJ_NUM) EMP_MJ_NM
		    FROM   EMP A
		    START WITH A.EMP_MJ_NUM IS NULL
		    CONNECT BY PRIOR A.EMP_NUM = A.EMP_MJ_NUM
		)
		SELECT COUNT(*) TOTAL
		FROM   T
		WHERE  1 = 1
		<include refid="where"></include>
	</select>
</mapper>

 

<EmMapper.java>

// 목록의 행의 수를 구함
	public int getTotal(Map<String, String> map);

<EmpService.java>

// 목록의 행의 수를 구함
	public int getTotal(Map<String, String> map);

 

<EmpServiceImpl.java>

	@Override
	public int getTotal(Map<String, String> map) {
		return this.empMapper.getTotal(map);

 

<EmpController.java>

@GetMapping("/list")
	public String list(Model model
			, @RequestParam Map<String,String> map
			, @RequestParam(value="currentPage",required=false,defaultValue="1") int currentPage
			, @RequestParam(value="show",required=false,defaultValue="10") int size){
		
		log.info("map : " + map);
		log.info("currentPage : " + currentPage);
		log.info("size : " + size);
		
		//map으로 파라미터를 받아서 매퍼xml에서 검색 조건으로 사용
		List<EmpVO> empVOList =  this.empService.list(map);
		log.info("empVOList : " + empVOList);
		
		//total
		int total = this.empService.getTotal(map);
		log.info("total : " + total);
		
		//size <- map.get("show")
//		int size = Integer.parseInt(map.get("show"));
		
		log.info("empVOList : " + empVOList);
		//empVOList 객체를 페이징 처리해보자
		//new ArticlePage<EmpVO>(total, currentPage, size, content)
		model.addAttribute("data", new ArticlePage<EmpVO>(total, currentPage, size, empVOList));
		//forwarding
		return "emp/list";
	}

 

<list.jsp>

  • <c:forEach var="empVO" items="${data.content}" varStatus="stat"> 
  • data.content로 바꿔준다.

 

  • ROW_NUMBER 는 정렬이 필요하지만
  • ROWNUM은 정렬 필요 없음

페이징 쿼리문

SELECT *
FROM
(
    WITH T AS(
        SELECT A.EMP_NUM, A.EMP_ADDR, A.EMP_PNE, A.EMP_NM, A.EMP_PAY
             , A.EMP_MJ_NUM
             , (SELECT B.EMP_NM FROM EMP B WHERE B.EMP_NUM = A.EMP_MJ_NUM) EMP_MJ_NM
        FROM   EMP A
        START WITH A.EMP_MJ_NUM IS NULL
        CONNECT BY PRIOR A.EMP_NUM = A.EMP_MJ_NUM
    )
    SELECT ROWNUM RNUM
         , T.EMP_NUM, T.EMP_ADDR, T.EMP_PNE, T.EMP_NM, T.EMP_PAY
         , T.EMP_MJ_NUM, T.EMP_MJ_NM
    FROM   T
    WHERE  1 = 1
    AND    (T.EMP_NUM = 'EMP007'
    OR     T.EMP_NM = 'EMP007'
    OR     T.EMP_MJ_NUM = 'EMP007')
) U
WHERE U.RNUM BETWEEN (1 * 10)-(10-1) AND (1 * 10)

 

<emp_SQL.xml>

list 고쳐줌

<!-- 직원 목록 -->
	<select id="list" parameterType="hashMap" resultType="empVO">
		SELECT *
		FROM
		(
		    WITH T AS(
		        SELECT A.EMP_NUM, A.EMP_ADDR, A.EMP_PNE, A.EMP_NM, A.EMP_PAY
		             , A.EMP_MJ_NUM
		             , (SELECT B.EMP_NM FROM EMP B WHERE B.EMP_NUM = A.EMP_MJ_NUM) EMP_MJ_NM
		        FROM   EMP A
		        START WITH A.EMP_MJ_NUM IS NULL
		        CONNECT BY PRIOR A.EMP_NUM = A.EMP_MJ_NUM
		    )
		    SELECT ROWNUM RNUM
		         , T.EMP_NUM, T.EMP_ADDR, T.EMP_PNE, T.EMP_NM, T.EMP_PAY
		         , T.EMP_MJ_NUM, T.EMP_MJ_NM
		    FROM   T
		    WHERE  1 = 1
		    <include refid="where"></include>
		) U
		WHERE U.RNUM BETWEEN (#{currentPage} * #{show})-(#{show}-1) AND (#{currentPage} * #{show})
	</select>

<EmpVO.java>

  • //행번호
    private int rnum;
  • 추가
package kr.or.ddit.vo;

import java.util.List;

import javax.validation.constraints.NotNull;

import org.hibernate.validator.constraints.NotBlank;

import lombok.Data;

//직원
@Data
public class EmpVO {
	//직원 번호
	@NotBlank
	private String empNum;
	//주소
	private String empAddr;
	//연락처
	@NotBlank
	private String empPne;
	//직원 명
	@NotBlank
	private String empNm;
	//급여
	@NotNull
	private int empPay;
	//매니저 번호
	private String empMjNum;
	//매니저명(EMP_MJ_NM)
	private String empMjNm;
	//행번호
	private int rnum;
	//직원(EMP) : 서비스(SER) = 1 : N
	private List<SerVO> serVOList;

}

 

<EmpController.java>

  • map에 currentPage, size를 추가해줘야함
  • map.put("currentPage", currentPage+"");
  • map.put("show", size+"");
  • // 1) /emp/list : show가 null
    // 2) /emp/list?show : show의 값이 없음
    if(map.get("show")==null || map.get("show").length()<1) {
    map.put("show", "10");
    }
@GetMapping("/list")
	public String list(Model model
			, @RequestParam Map<String,String> map
			, @RequestParam(value="currentPage",required=false,defaultValue="1") int currentPage
			, @RequestParam(value="show",required=false,defaultValue="10") int size){
		
		log.info("map : " + map);
		log.info("currentPage : " + currentPage);
		log.info("size : " + size);
		
		map.put("currentPage", currentPage+"");
      
      	// 1) /emp/list : show가 null
		// 2) /emp/list?show : show의 값이 없음
		if(map.get("show")==null || map.get("show").length()<1) {
			map.put("show", "10");
		}
		
		//map으로 파라미터를 받아서 매퍼xml에서 검색 조건으로 사용
		List<EmpVO> empVOList =  this.empService.list(map);
		log.info("empVOList : " + empVOList);
		
		//total
		int total = this.empService.getTotal(map);
		log.info("total : " + total);
		
		//size <- map.get("show")
//		int size = Integer.parseInt(map.get("show"));
		
		log.info("empVOList : " + empVOList);
		//empVOList 객체를 페이징 처리해보자
		//new ArticlePage<EmpVO>(total, currentPage, size, content)
		model.addAttribute("data", new ArticlePage<EmpVO>(total, currentPage, size, empVOList));
		//forwarding
		return "emp/list";
	}

 

<list.jsp>

  • 페이징처리를해주자.

 

<%@ page language="java" contentType="text/html;charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<link rel="stylesheet" href="/resources/css/bootstrap.min.css" />
<link rel="stylesheet" href="/resources/css/sweetalert2.min.css" />
<script type="text/javascript" src="/resources/js/bootstrap.min.js"></script>
<script src="https://ssl.daumcdn.net/dmaps/map_js_init/postcode.v2.js"></script>
<script type="text/javascript" src="/resources/js/jquery-3.6.0.js"></script>
<script type="text/javascript" src="/resources/js/sweetalert2.min.js"></script>
<div class="card shadow mb-4">
	<div class="card-header py-3">
		<h6 class="m-0 font-weight-bold text-primary">직원목록</h6>
	</div>
	<div class="card-body">
		<div class="table-responsive">
			<div id="dataTable_wrapper" class="dataTables_wrapper dt-bootstrap4">
			<!-- 검색 영역 시작 action을 생략하면 현재의 URI, method를 생략하면 기본이 get -->
			<form name="frm" id="frm" action="/emp/list" method="get">
				<div class="row">
					<div class="col-sm-12 col-md-6">
						<div class="dataTables_length" id="dataTable_length">
							<label>Show 
							<!-- 한 화면에 보여질 행의 수 -->
							<select 
								aria-controls="dataTable"
								name="show" id="show"
								class="custom-select custom-select-sm form-control form-control-sm"><option
										value="10">10</option>
									<option value="25">25</option>
									<option value="50">50</option>
									<option value="100">100</option></select> entries
							</label>
						</div>
					</div>
					<div class="col-sm-12 col-md-6">
						<div id="dataTable_filter" class="dataTables_filter">
							<label>Search:<input type="search" name="keyword" 
								class="form-control form-control-sm" 
								placeholder="검색어를 입력해주세요"
								aria-controls="dataTable"
								value="${param.keyword}">
							</label>
							<label>
								<button type="submit" class="btn btn-primary btn-icon-split btn-sm">
									<span class="icon text-white-50">
										<i class="fas fa-flag"></i>
									</span>
									<span class="text">검색</span>
								</button>
							</label>
						</div>
					</div>
				</div>
			</form>
			<!-- 검색 영역 끝 -->				
				<div class="row">
					<div class="col-sm-12">
						<table class="table table-bordered dataTable" id="dataTable"
							width="100%" cellspacing="0" role="grid"
							aria-describedby="dataTable_info" style="width: 100%;">
							<thead>
								<tr role="row">
									<th class="sorting sorting_asc" tabindex="0"
										aria-controls="dataTable" rowspan="1" colspan="1"
										aria-sort="ascending"
										aria-label="Name: activate to sort column descending"
										style="width: 66px;">번호</th>
									<th class="sorting" tabindex="0" aria-controls="dataTable"
										rowspan="1" colspan="1"
										aria-label="Position: activate to sort column ascending"
										style="width: 79px;">직원번호</th>
									<th class="sorting" tabindex="0" aria-controls="dataTable"
										rowspan="1" colspan="1"
										aria-label="Office: activate to sort column ascending"
										style="width: 54px;">직원명</th>
									<th class="sorting" tabindex="0" aria-controls="dataTable"
										rowspan="1" colspan="1"
										aria-label="Age: activate to sort column ascending"
										style="width: 31px;">급여</th>
									<th class="sorting" tabindex="0" aria-controls="dataTable"
										rowspan="1" colspan="1"
										aria-label="Start date: activate to sort column ascending"
										style="width: 69px;">매니저</th>
								</tr>
							</thead>
							<tbody>
								<!-- data : List<EmpVO> empVOList 
									empVO : EmpVO
								stat.index : 0부터 시작
								stat.count : 1부터 시작
								
								data : AtriclePage
								data.content : ArticlePage의 content 멤버변수(List<EmpVO>)
								-->
								<c:forEach var="empVO" items="${data.content}" varStatus="stat">
								<tr class="odd">
									<td class="sorting_1">${empVO.rnum}</td>
									<td><a href="/emp/detail?empNum=${empVO.empNum}">${empVO.empNum}</a></td>
									<td>${empVO.empNm}</td>
									<td>${empVO.empPay}</td>
									<td data-bs-toggle="modal" data-bs-target="#exampleModal">
										<a class="showMj" data-emp-mj-num="${empVO.empMjNum}" 
										data-bs-toggle="modal" href="#exampleModal">${empVO.empMjNm}</a>
									</td>
								</tr>
								</c:forEach>
							</tbody>
						</table>
					</div>
				</div>
				<div class="row">
					<div class="col-sm-12 col-md-5">
						<div class="dataTables_info" id="dataTable_info" role="status"
							aria-live="polite">Showing 1 to 10 of 57 entries</div>
					</div>
					<div class="col-sm-12 col-md-7">
						<div class="dataTables_paginate paging_simple_numbers"
							id="dataTable_paginate">
							<ul class="pagination">
								<li class="paginate_button page-item previous 
									<c:if test='${data.startPage <6 }'>disabled</c:if>
								"id="dataTable_previous">
								<!-- keyword${param.keyword} -->
								<a href="/emp/list?currentPage=${data.startPage-5}&keyword=${param.keyword}"
									aria-controls="dataTable" data-dt-idx="0" tabindex="0"
									class="page-link">Previous</a></li>
								<c:forEach var="pNo" begin="${data.startPage}" end="${data.endPage}">
								<li class="paginate_button page-item
										<c:if test='${param.currentPage==pNo}'>active</c:if>
									 ">
									<a href="/emp/list?currentPage=${pNo}&keyword=${param.keyword}"
									aria-controls="dataTable" data-dt-idx="1" tabindex="0"
									class="page-link">${pNo}</a></li>
									</c:forEach>
								<li class="paginate_button page-item next
									<c:if test='${data.endPage == data.totalPages}'>disabled</c:if>
								" id="dataTable_next">
								<a href="/emp/list?currentPage=${data.startPage+5}&keyword=${param.keyword}" aria-controls="dataTable" data-dt-idx="7" tabindex="0"
									class="page-link">Next</a></li>
							</ul>
						</div>
					</div>
				</div>
			</div>
		</div>
	</div>
</div>
<!-- Modal -->
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h1 class="modal-title fs-5" id="exampleModalLabel">매니저정보</h1>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        <!-- 내용 시작 -->
         <div class="mb-3 row">
		    <label for="staticEmail" class="col-sm-2 col-form-label">직원 번호</label>
		    <div class="col-sm-10">
		      <input type="text" readonly class="form-control-plaintext" id="empNum" value="">
		    </div>
		  </div>
         <div class="mb-3 row">
		    <label for="staticEmail" class="col-sm-2 col-form-label">직원 명</label>
		    <div class="col-sm-10">
		      <input type="text" readonly class="form-control-plaintext" id="empNm" value="">
		    </div>
		  </div>
         <div class="mb-3 row">
		    <label for="staticEmail" class="col-sm-2 col-form-label">연락처</label>
		    <div class="col-sm-10">
		      <input type="text" readonly class="form-control-plaintext" id="empPne" value="">
		    </div>
		  </div>
         <div class="mb-3 row">
		    <label for="staticEmail" class="col-sm-2 col-form-label">주소</label>
		    <div class="col-sm-10">
		      <input type="text" readonly class="form-control-plaintext" id="empAddr" value="">
		    </div>
		  </div>
         <div class="mb-3 row">
		    <label for="staticEmail" class="col-sm-2 col-form-label">급여</label>
		    <div class="col-sm-10">
		      <input type="text" readonly class="form-control-plaintext" id="empPay" value="">
		    </div>
		  </div>
         <div class="mb-3 row">
		    <label for="staticEmail" class="col-sm-2 col-form-label">매니저</label>
		    <div class="col-sm-10">
		      <input type="text" readonly class="form-control-plaintext" id="empMjNm" value="">
		    </div>
		  </div>
        <!-- 내용 끝 -->
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
      </div>
    </div>
  </div>
</div>
<script type="text/javascript">
$(function(){
// 	$(document).on("click",".showMj",function(){
	$(".showMj").on("click",function(){
		console.log("ajax로 매니저 정보 가져와보자");
		console.log("요청URI : /emp/showMj");
		console.log("요청파라미터(json) : {'empNum':'EMP006'}");
		console.log("요청방식 : post");
		//this : class="showMj"이 여러개이고, 이 중에서 하나를 클릭한 바로 그 요소
		//data-emp-mj-num="EMP006"
		let empMjNum = $(this).data("empMjNum");
		console.log("empMjNum : " + empMjNum);
		
		//json object
		let data = {"empMjNum":empMjNum};
		
		$.ajax({
			url:"/emp/showMj",
			contentType:"application/json;charset:utf-8",
			data:JSON.stringify(data),//마샬링,일렬화(serialization)
			type:"post",
			dataType:"json",
			
			success:function(result){
				//result : {"empNum":"EMP006","empAddr":"12345 제주특별자치도 제주시 첨단로 242 개똥이빌딩 405"
// 					,"empPne":"010-123-1234","empNm":"개똥이","empPay":12345,"empMjNum":"EMP002"
// 					,"empMjNm":"김철수","serVOList":null}
				console.log("result : " + JSON.stringify(result));
				
				$("#empNum").val(result.empNum);
				$("#empNm").val(result.empNm);
				$("#empPne").val(result.empPne);
				$("#empAddr").val(result.empAddr);
				$("#empPay").val(result.empPay);
				$("#empMjNm").val(result.empMjNm);
			}
		});
		
	});
});
</script>

 

우선 DB에 데이터를 넣어보자

 

SET SERVEROUTPUT ON;
/
DECLARE
BEGIN
    FOR I IN 1..123 LOOP
    INSERT INTO EMP(EMP_NUM, EMP_ADDR, EMP_PNE, EMP_NM, EMP_PAY, EMP_MJ_NUM)
    VALUES(
        (SELECT NVL(SUBSTR(MAX(EMP_NUM),1,3),'EMP')
                 || TRIM(TO_CHAR(NVL(SUBSTR(MAX(EMP_NUM),4),0) + 1,'000'))
            FROM   EMP),
        '우리집'||I,'010-123-1234','새롬이'||I,100000,'');
    END LOOP;
    COMMIT;
    DBMS_OUTPUT.PUT_LINE('완료');
END;
/

 


SHOW (화면에 보여질 목록수 변경) on change

<list.jsp>

 

<label>Show 
<!-- 한 화면에 보여질 행의 수 -->
<select 
    aria-controls="dataTable"
    name="show" id="show"
    class="custom-select custom-select-sm form-control form-control-sm">
    <option value="10" <c:if test="${param.show == 10}">selected</c:if>>10</option>
        <option value="25" <c:if test="${param.show == 25}">selected</c:if>>25</option>
        <option value="50" <c:if test="${param.show == 50}">selected</c:if>>50</option>
        <option value="100" <c:if test="${param.show == 100}">selected</c:if>>100</option></select> entries
</label>

 

하단에 스크립트 생성

//show가 바뀜
	$("#show").on("change",function(){
		//currentPage=1&keyword=개똥이&show=10
		let currentPage = "${param.currentPage}";
		let keyword = "${param.keyword}";
		
		console.log("currentPage : " + currentPage + ", keyword : " + keyword);
		
		let show = $(this).val();
		let show2 = $("#show option:selected").val();
		let show3 = $("select[name='show']").val();
		let show4 = $("#show option").index($("#show option:selected"));
		
		console.log("show : " + show);
		
		location.href="/emp/list?show="+show+"&currentPage=1&keyword="+keyword;
	});

고정된다 


++ tr의 class odd/even 으로 나누기

 

++ 화면 밑단에 게시글 개수 보이게 설정

<div class="row">
            <div class="col-sm-12 col-md-5">
                <div class="dataTables_info" id="dataTable_info" role="status"
                    aria-live="polite">
                    <c:if test="${param.show==null}">
                        <c:set var="show" value="1" />
                    </c:if>
                    <c:if test="${param.show!=null}">
                        <c:set var="show" value="${param.show}" />
                    </c:if>
                    <!-- scope(공유영역) : page(기본), request, session, application -->
                    <!-- 종료행 : currentPage * show -->
                    <c:set var="endRow" value="${data.currentPage * show}" />							
                    <!-- 시작행 : 종료행 - (size-1) -->
                    <c:set var="startRow" value="${endRow - (show-1)}" />
                    <!-- 전체행수 : total -->
                    <c:if test="${endRow > data.total}">
                        <c:set var="endRow" value="${data.total}"/>
                     </c:if>
                    Showing ${startRow} to ${endRow} of ${data.total} entries
                </div>
            </div>
Comments