Spring

Spring 17 - 데이터베이스 구축부터 CRUD까지 (다음 우편번호 api 활용)

inderrom 2023. 2. 3. 17:34

개념 설계 : 개체 - 관계 설정

 

개체

  • 명사
  • 핵심 개념
  • 명확해야함
  • 구별이 되어야함

 

밑줄 - 기본키

데이터 베이스에서는 다대다 관계를 처리할 수 없다.

 

 

자료사전

 

 

ERD를 DB로 넣는 것을 FORWARD 엔지니어링

반대로 넣는 것은 REVERSE 엔지니어링

 

클립복사

복사 후 sql developer 에서 쿼리문 실행

테이블에 MY_SCHEMA. 을 없애주기 위해 ctrl+f로 찾아서 공백으로 바꾼다.


 

고객, 직원, 자동차, 서비스의 VO를 만들어주자

 

 

<CusVO.java>

오라클에서 카멜 표기법

SELECT COLUMN_NAME
, DATA_TYPE
, CASE WHEN DATA_TYPE='NUMBER' THEN 'private int ' || FN_GETCAMEL(COLUMN_NAME) || ';'
WHEN DATA_TYPE IN('VARCHAR2','CHAR') THEN 'private String ' || FN_GETCAMEL(COLUMN_NAME) || ';'
WHEN DATA_TYPE='DATE' THEN 'private Date ' || FN_GETCAMEL(COLUMN_NAME) || ';'
ELSE 'private String ' || FN_GETCAMEL(COLUMN_NAME) || ';'
END AS CAMEL_CASE
, '' RESULTMAP
FROM ALL_TAB_COLUMNS
WHERE TABLE_NAME = 'CUS';
/

멤버변수로 만들기

package kr.or.ddit.vo;

import java.util.List;

import lombok.Data;

//고객
@Data
public class CusVO {
	// 고객번호
	private String cusNum;
	// 고객명
	private String cusNm;
	// 주소
	private String cusAddr;
	// 연락처
	private String cusPhe;
	// 고객(CUS) : 자동차(CAR) = 1 : N
	private List<CarVO> carVOList;
	// 고객(CUS) : 서비스(SER) = 1 : N
	private List<SerVO> serVOList;
}

 

 

<EmpVO.java>

package kr.or.ddit.vo;

import java.util.List;

import lombok.Data;

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

 

<CarVO.java>

package kr.or.ddit.vo;

import java.util.Date;
import java.util.List;

import lombok.Data;

@Data
// 자동차
public class CarVO {
	// 자동차 번호
	private String cusNum;
	// 제조 번호
	private String mmfNum;
	// 연식
	private Date dt;
	// 주행 거리
	private int dist;
	// 고객 번호
	private String carNm;
	//자동차(CAR) : 서비스(SER) 1: N
	private List<SerVO> serVOList;
}

 

<SerVO.java>

package kr.or.ddit.vo;

//서비스
public class SerVO {
	//서비스 번호
	private String serNum;
	//수리비
	private int serCs;
	//수리 시간
	private int serTm;
	//고객 번호
	private String cusNum;
	//직원 번호
	private String empNum;
	//자동차 번호
	private String carNum;
}

 

 

유효성 검사를 위한 의존 라이브러리 등록

  • hibernate-validator 5.4.2

<pom.xml>

		<!-- 입력값을 검증하기 위한 라이브러리 의존 관계 정의 시작 -->
		<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-validator -->
		<dependency>
		    <groupId>org.hibernate</groupId>
		    <artifactId>hibernate-validator</artifactId>
		    <version>5.4.2.Final</version>
		</dependency>
		<!-- 입력값을 검증하기 위한 라이브러리 의존 관계 정의 끝 -->

 

run as - maven build

 

 

<CusVO.java>

  • @NotBlank 추가해주기 
package kr.or.ddit.vo;

import java.util.List;

import org.hibernate.validator.constraints.NotBlank;

import lombok.Data;

//고객
/* Bean Validation이 제공하는 제약 애너테이션
 - NotNull : 빈 값 체크
 - *NotBlank : null 체크, trim(공백제거) 후 길이가 0인지 체크
 - Size : 글자 수 체크
 - Email : 이메일 주소 형식 체크
 - Past : 오늘보다 과거 날짜(ex. 생일)
 - Future : 미래 날짜 체크(ex. 예약일)
 */
@Data
public class CusVO {
	//고객번호(필수=mandatory), null 체크, trim 후 길이가 0인지 체크
	@NotBlank
	private String cusNum;
	//고객명
	@NotBlank
	private String cusNm;
	//주소
	private String cusAddr;
	//연락처
	@NotBlank
	private String cusPhe;
	//고객(CUS) : 자동차(CAR) = 1 : N
	private List<CarVO> carVOList;
	//고객(CUS) : 서비스(SER) = 1 : N
	private List<SerVO> serVOList;
}

 

<EmpVO.java>

  • NotBlank 추가
package kr.or.ddit.vo;

import java.util.List;

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;
	//급여
	@NotBlank
	private int empPay;
	//직원(EMP) : 서비스(SER) = 1 : N
	private List<SerVO> serVOList;
}

 

<CarVO.java>

  • NotBlank 추가 (carNum)
package kr.or.ddit.vo;

import java.util.Date;
import java.util.List;

import org.hibernate.validator.constraints.NotBlank;

//자동차
public class CarVO {
	//자동차 번호
	@NotBlank
	private String carNum;
	//제조 번호
	@NotBlank
	private String mnfNum;
	//연식
	private Date dt;
	//주행 거리
	private int dist;
	//고객 번호
	@NotBlank
	private String cusNum;
	//자동차(CAR) : 서비스(SER) = 1 : N
	private List<SerVO> serVOList;
}

 

 

SerVO를 고치기 전에 CUS 테이블에 우편번호와, 상세주소 컬럼을 추가해주자

  • SQL DEVELOPER에 가서 편집 후 추가
  • POSTNO, ADDR_DET

그리고 다시 CusVO 가서 수정

package kr.or.ddit.vo;

import java.util.List;

import org.hibernate.validator.constraints.NotBlank;

import lombok.Data;

//고객
/* Bean Validation이 제공하는 제약 애너테이션
 - NotNull : 빈 값 체크
 - *NotBlank : null 체크, trim(공백제거) 후 길이가 0인지 체크
 - Size : 글자 수 체크
 - Email : 이메일 주소 형식 체크
 - Past : 오늘보다 과거 날짜(ex. 생일)
 - Future : 미래 날짜 체크(ex. 예약일)
 */
@Data
public class CusVO {
	//고객번호(필수=mandatory), null 체크, trim 후 길이가 0인지 체크
	@NotBlank
	private String cusNum;
	//고객명
	@NotBlank
	private String cusNm;
	//주소
	private String cusAddr;
	//연락처
	@NotBlank
	private String cusPhe;
	//우편번호
	private String postno;
	//주소 상세
	private String addrDet;
	//고객(CUS) : 자동차(CAR) = 1 : N
	private List<CarVO> carVOList;
	//고객(CUS) : 서비스(SER) = 1 : N
	private List<SerVO> serVOList;
}

 

<SerVO.java>

package kr.or.ddit.vo;

import java.util.Date;

import javax.validation.constraints.Future;
import javax.validation.constraints.Size;

import org.hibernate.validator.constraints.NotBlank;
import org.springframework.format.annotation.DateTimeFormat;

//서비스
public class SerVO {
	//서비스 번호
	@NotBlank
	private String serNum;
	//수리비
	@NotBlank
	private int serCs;
	//수리 시간
	@Size(max=3)
	private int serTm;
	//수리 완료 예정일
	//미래 날짜인지 검사(23/02/03(x), 2023-02-03(o)..)
	@Future
	@DateTimeFormat(pattern="yyyy-MM-dd")
	private Date repCompDt;
	//고객 번호
	private String cusNum;
	//직원 번호
	private String empNum;
	//자동차 번호
	private String carNum;
}

 


 

<aside.jsp> 수정

 

도서관리 밑에 고객관리를 만든다.

    <!-- 고객관리 -->
    <li class="nav-item">
        <a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapseCus"
            aria-expanded="true" aria-controls="collapseCus">
            <i class="fas fa-fw fa-spinner"></i>
            <span>고객관리</span>
        </a>
        <div id="collapseCus" 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="/cus/create">고객등록</a>
                <a class="collapse-item" href="/cus/list">고객목록</a>
            </div>
        </div>
    </li>

메뉴바에 고객관리가 추가됨

 


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="bd-example">
<div class="mb-3">
  <label for="exampleFormControlInput1" class="form-label">Email address</label>
  <input type="email" class="form-control" id="exampleFormControlInput1" placeholder="name@example.com">
</div>
<div class="mb-3">
  <label for="exampleFormControlTextarea1" class="form-label">Example textarea</label>
  <textarea class="form-control" id="exampleFormControlTextarea1" rows="3"></textarea>
</div>
</div>

부트스트랩에서 소스 복사 후 create.jsp에 붙혀넣자

 

views 아래에 cus폴더 create.jsp 만든다.

 

<create.jsp>

<%@ page language="java" contentType="text/html;charset=UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!-- ctrl + shift + F : 인덴트 자동 처리 -->
<div class="bd-example">
	<div class="mb-3">
		<label for="exampleFormControlInput1" class="form-label">Email
			address</label> <input type="email" class="form-control"
			id="exampleFormControlInput1" placeholder="name@example.com">
	</div>
	<div class="mb-3">
		<label for="exampleFormControlTextarea1" class="form-label">Example
			textarea</label>
		<textarea class="form-control" id="exampleFormControlTextarea1"
			rows="3"></textarea>
	</div>
</div>

 

 

<CusController.java>

package kr.or.ddit.controller;

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

import lombok.extern.slf4j.Slf4j;
// Controller -> 자바빈으로 등록해서 관리
// 속성이 1개일 땐 속성명 생략 가능 (value= << 이 속성이 생략되어있음)
@Slf4j
@RequestMapping("/cus")
@Controller
public class CusController {
	
	// void로 응답
	// 요청URI : /cus/create
	@GetMapping("/create")
	public void create() {
		log.info("create()에 왔다");
		// forwarding
		//return "cus/create"
	}
}

 

 

네비바 추가

https://getbootstrap.com/docs/5.3/components/navbar/

<nav class="navbar bg-body-tertiary">
	<div class="container-fluid">
		<a class="navbar-brand" href="#">고객관리</a>
	</div>
</nav>

 

<create.jsp>

  • 라벨은 labet for에 해당하는 것을 눌렀을 때 포커스를 주는 것 
<%@ 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" />

<!-- ctrl + shift + F : 인덴트 자동 처리 -->
<nav class="navbar bg-body-tertiary">
  <div class="container-fluid">
    <a class="navbar-brand" href="#">고객관리</a>
  </div>
</nav>
<div class="bd-example">
	<div class="mb-3">
		<label for="cusNum" class="form-label">고객번호</label> 
		<input type="text" class="form-control"
			id="cusNum" name="cusNum" placeholder="고객번호를 입력해주세요" />
	</div>
	<div class="mb-3">
		<label for="cusNm" class="form-label">고객명</label> 
		<input type="text" class="form-control"
			id="cusNm" name="cusNm" placeholder="고객명을 입력해주세요" />
	</div>
	<div class="mb-3">
		<div>
			<label for="postno" class="form-label">우편번호</label>
		</div>
		<div> 
			<input type="text" class="form-control"
				id="postno" name="postno" placeholder="우편번호를 입력해주세요"
				style="width:80%;float:left;" />
			<input class="btn btn-info" type="button" value="우편번호 검색"
				style="width:20%;float:right;" />
		</div>
	</div>
	<div class="mb-3">
		<label for="cusAddr" class="form-label">주소</label> 
		<input type="text" class="form-control"
			id="cusAddr" name="cusAddr" placeholder="주소를 입력해주세요" />
	</div>
	<div class="mb-3">
		<label for="addrDet" class="form-label">상세 주소</label> 
		<input type="text" class="form-control"
			id="addrDet" name="addrDet" placeholder="상세 주소를 입력해주세요" />
	</div>
	<div class="mb-3">
		<label for="cusPhe" class="form-label">연락처</label> 
		<input type="text" class="form-control"
			id="cusPhe" name="cusPhe" placeholder="연락처를 입력해주세요" />
	</div>
</div>

 

 


다음 지도 api 적용하기

<create.jsp>

  • 우편번호 검색에 아이디를 준다. btnPostno
  • 스크립트 작성

$(function(){
	// 다음 우편번호 검색
	$("#btnPostno").on("click", function(){
		new daum.Postcode({
			// 다음 창에서 검색이 완료되면 콜백함수에 의해 결과 데이터가 data 객체로 들어옴
			oncomplete:function(data){
				// 우편번호
				$("#postno").val(data.zonecode);
				// 주소
				$("#cusAddr").val(data.address);
				// 상세 주소
				$("#addrDet").val(data.buildingName);
			}
		}).open();
	});
}) ;

실행 시키고 우편번호를 누르면 다음 api가 실행되는 걸 볼 수 있다.

 

<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){
				// 우편번호
				$("#postno").val(data.zonecode);
				// 주소
				$("#cusAddr").val(data.address);
				// 상세 주소
				$("#addrDet").val(data.buildingName);
			}
		}).open();
	});
}) ;
</script>
<!-- ctrl + shift + F : 인덴트 자동 처리 -->
<nav class="navbar bg-body-tertiary">
  <div class="container-fluid">
    <a class="navbar-brand" href="#">고객관리</a>
  </div>
</nav>
<!-- 폼페이지
요청URI : /cus/createPost
요청파라미터 : {cusNum=1234, cusNm=새롬이, postno=33233...}
요청방식 : post
 - modelAttribute="cusVO" => 컨트롤러에서 매게변수에 담아줬던 데이터를 연결해주는 것 
    꼭 이름을 같게 설정할 것
 -->
<form:form modelAttribute="cusVO" action="/cus/createPost" method="post">
<!-- 폼데이터 -->
<div class="bd-example">
	<div class="mb-3">
		<label for="cusNum" class="form-label">고객번호</label> 
		<input type="text" class="form-control"
			id="cusNum" name="cusNum" placeholder="고객번호를 입력해주세요" />
		<!-- path : cusVO객체의  cusNum 멤버변수 -->	
		<form:errors path="cusNum" style="color:red;" />
	</div>
	<div class="mb-3">
		<label for="cusNm" class="form-label">고객명</label> 
		<input type="text" class="form-control"
			id="cusNm" name="cusNm" placeholder="고객명을 입력해주세요" />
		<form:errors path="cusNm" style="color:red;" />
	</div>
	<div class="mb-3">
		<div>
			<label for="postno" class="form-label">우편번호</label>
		</div>
		<div> 
			<input type="text" class="form-control"
				id="postno" name="postno" placeholder="우편번호를 입력해주세요"
				style="width:80%;float:left;" />
			<input class="btn btn-info" type="button" value="우편번호 검색"
				style="width:20%;float:right;" id="btnPostno" />
		</div>
	</div>
	<div class="mb-3">
		<label for="cusAddr" class="form-label">주소</label> 
		<input type="text" class="form-control"
			id="cusAddr" name="cusAddr" placeholder="주소를 입력해주세요" />
	</div>
	<div class="mb-3">
		<label for="addrDet" class="form-label">상세 주소</label> 
		<input type="text" class="form-control"
			id="addrDet" name="addrDet" placeholder="상세 주소를 입력해주세요" />
	</div>
	<div class="mb-3">
		<label for="cusPhe" class="form-label">연락처</label> 
		<input type="text" class="form-control"
			id="cusPhe" name="cusPhe" placeholder="연락처를 입력해주세요" />
		<form:errors path="cusPhe" style="color:red;" />
	</div>
	<div>
		<button type="submit" class="btn btn-primary btn-lg">등록</button>
	</div>
</div>
</form:form>

 

<CusVO.java>

  • @Size(min=2,max=10,message="2~10자 이내로 입력해 주세요")
package kr.or.ddit.vo;

import java.util.List;

import javax.validation.constraints.Size;

import org.hibernate.validator.constraints.NotBlank;

import lombok.Data;

//고객
/* Bean Validation이 제공하는 제약 애너테이션
 - NotNull : 빈 값 체크
 - *NotBlank : null 체크, trim(공백제거) 후 길이가 0인지 체크
 - Size : 글자 수 체크
 - Email : 이메일 주소 형식 체크
 - Past : 오늘보다 과거 날짜(ex. 생일)
 - Future : 미래 날짜 체크(ex. 예약일)
 */
@Data
public class CusVO {
	//고객번호(필수=mandatory), null 체크, trim 후 길이가 0인지 체크
	@NotBlank
	private String cusNum;
	//고객명
	@NotBlank
	@Size(min=2,max=10,message="2~10자 이내로 입력해 주세요")
	private String cusNm;
	//주소
	private String cusAddr;
	//연락처
	@NotBlank
	private String cusPhe;
	//우편번호
	private String postno;
	//주소 상세
	private String addrDet;
	//고객(CUS) : 자동차(CAR) = 1 : N
	private List<CarVO> carVOList;
	//고객(CUS) : 서비스(SER) = 1 : N
	private List<SerVO> serVOList;
}

 

<CusController.java>

package kr.or.ddit.controller;

import javax.validation.Valid;

import org.springframework.stereotype.Controller;
import org.springframework.validation.Errors;
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 kr.or.ddit.vo.CusVO;
import lombok.extern.slf4j.Slf4j;
// Controller -> 자바빈으로 등록해서 관리
// 속성이 1개일 땐 속성명 생략 가능 (value= << 이 속성이 생략되어있음)
@Slf4j
@RequestMapping("/cus")
@Controller
public class CusController {
	
	// void로 응답
	// 요청URI : /cus/create
	@GetMapping("/create")
	public void create() {
		log.info("create()에 왔다");
		// forwarding
		//return "cus/create"
	}
	
	// String으로 응답*
	/*
	 요청URI : /cus/createPost
	요청파라미터 : {cusNum=1234, cusNm=새롬이, postno=33233...}
	요청방식 : post
	 */
	// String, int, Map.. => @RequestParam
	// VO => ModelAttribute
	// @Valid => CusVO의 validation 체크를 해주는 애너테이션
	// 문제발생 시 Errors errors객체에 오류 정보를 담아서  꼭!!! forwarding 해주면 됨
	@PostMapping("/createPost")
	public String createPost(@Valid @ModelAttribute CusVO cusVO,
			Errors errors) {
		
		// errors.hasErrors() : 문제 발생 시 true
		if(errors.hasErrors()) {
			return "cus/create"; 
		}
		
		// 입력성공 : 상세보기로 redirect. 기본키 데이터를 파라미터로 보냄
		return "redirect:/cus/detail?cusNum="+cusVO.getCusNum();
	}
	
}

 

error 를 넣어줬기 때문에 실행 시킬 때
에러메세지를 출력할 수 있다.

 

 


상세보기 (detail)

 

 

쿼리문

  • INNER JOIN 을 해줘도 된다.
-- ANSL 표준 INNER JOIN
SELECT A.CUS_NUM, A.CUS_NM, A.CUS_ADDR, A.CUS_PHE, A.POSTNO, A.ADDR_DET, A.CUS_BIR, A.HOBBY, A.GENDER, A.NATIONALITY
    , B.CAR_NM,  B.MMF_NUM,  B.DT,  B.DIST
FROM CUS A LEFT OUTER JOIN CAR B
ON( A.CUS_NUM = B.CUS_NUM)
WHERE A.CUS_NUM ='CUS004';

 

 

<cus_SQL.xml>

  • 상세보기 쿼리문 수정
  • 고객: 자동차 (1: N) 쿼리문
	<!-- 고객 : 자동차 = 1 : N -->
	 <resultMap type="cusVO" id="cusMap">
	 	<result property="cusNum" column="CUS_NUM" /> 
		<result property="cusNm" column="CUS_NM" /> 
		<result property="cusAddr" column="CUS_ADDR" /> 
		<result property="cusPhe" column="CUS_PHE" /> 
		<result property="postno" column="POSTNO" /> 
		<result property="addrDet" column="ADDR_DET" /> 
		<result property="cusBir" column="CUS_BIR" /> 
		<result property="hobby" column="HOBBY" /> 
		<result property="gender" column="GENDER" /> 
		<result property="nationality" column="NATIONALITY" />
		<collection property="carVOList" resultMap="carMap"></collection> 
	 </resultMap>
	 
	 <resultMap type="carVO" id="carMap">
	 	<result property="carNum" column="CAR_NUM" /> 
		<result property="mnfNum" column="MNF_NUM" /> 
		<result property="dt" column="DT" /> 
		<result property="dist" column="DIST" /> 
		<result property="cusNum" column="CUS_NUM" /> 
	 </resultMap>
	 
	 <!-- 고객 상세보기 -->
	 <select id="detail" parameterType="cusVO" resultMap="cusMap">
	 	SELECT A.CUS_NUM, A.CUS_NM, A.CUS_ADDR, A.CUS_PHE, A.POSTNO, A.ADDR_DET, A.CUS_BIR, A.HOBBY, A.GENDER, A.NATIONALITY
		     , B.CAR_NUM, B.MNF_NUM, B.DT, B.DIST
		FROM   CUS A INNER JOIN CAR B ON(A.CUS_NUM = B.CUS_NUM)
		WHERE  A.CUS_NUM = #{cusNum}
	 </select>

 

여기서 잠깐!

저번에 만들어 놓은 CAR 테이블 컬럼  수정

  • CAR_NM ==> CAR_NUM
  • MNF_NUM ==> MMF_NUM 으로 수정한다 

- VO에서는 컬럼을 잘 생성했는데

- 테이블 컬럼명 설정을 잘못함

- 꼭 수정해야 오류가 나지 않는다.


 

 

 

value를 가져올 때는 
value="${ }" 를 쓰는 방법과
폼태그 라이브러리를 사용하는 방법이 있다.
<form:input path="${}" 를 써주면 
이 태그 안에는 id, name , value가 다 자동으로 바인딩 되어서
value값이 들어가게 된다.
둘 중 골라 씀!

 

 

 

<cusController.java>

  • 처음에 model.addAttribute("data", cusVO); 로 매핑했던 것을 cusVO,cusVO 로 바꿔서 매핑한다.
  • 파라미터, jsp에서 쓰는 <form:form modelAttribute="cusVO" action="/cus/createPost" method="post"> 에서 
  • 변수명이 다 같아야 값이 셋팅 된다.
/* 컨트롤러 매서드 매개변수
	 - String
	 - Model
	 - RedirectAttributes
	 - 자바빈즈 클래스
	 - MultipartFile 
	 - BindingResult
	 - java.util.Locale
	 - java.security.Principal 
	 */
	//요청URI : /cus/detail?cusNum=CUS002
	@GetMapping("/detail")
	public String detail( Model model, RedirectAttributes ras,
			@ModelAttribute CusVO cusVO) {
		
		// 상세보기
		cusVO = this.cusService.detail(cusVO);
		//[0]    [1]   [2]
		//str += str + ",";
		//Music,Sports,
		String hobby = cusVO.getHobby();
		String[] hobbyArray = hobby.split(",");
		List<String> hobbyList = new ArrayList<String>();
		for(int i=0;i<hobbyArray.length;i++) {
			hobbyList.add(hobbyArray[i]);
		}
		cusVO.setHobbyList(hobbyList);
	
		
		log.info("cusVO(after) : " + cusVO);
		
		// 국적(한개 선택) => selelct박스
		Map<String, String> nationalityMap = new HashMap<String, String>();
		nationalityMap.put("Korea", "Korea");
		nationalityMap.put("English", "English");
		nationalityMap.put("Germany", "Germany");
		
		model.addAttribute("nationalityMap",nationalityMap);
		model.addAttribute("cusVO", cusVO);
		
		//forwarding
		return "cus/detail";
	}

 

 

 

<detail.jsp>

  • value로 값 고정, readonly, disable
  • 취미의 경우 배열로 값을 가져온다.
  • 생일의 경우  input type 을 text로 바꾸고 fmt로 꺼내줌
  • value="<fmt:formatDate pattern='yyyy-MM-dd' value='${cusVO.cusBir }'/>" />
  •  주행거리는 foreach로 출력 <c:forEach var="carVO" items="${cusVO.carVOList}" varStatus="stat">
<%@ page language="java" contentType="text/html;charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%@ 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){
				// 우편번호
				$("#postno").val(cusVO.zonecode);
				// 주소
				$("#cusAddr").val(cusVO.address);
				// 상세 주소
				$("#addrDet").val(cusVO.buildingName);
			}
		}).open();
	});
	
	
	$("input").prop("readonly","true");
	 $('option').attr('disabled', true);
	
}) ;
</script>
<!-- ctrl + shift + F : 인덴트 자동 처리 -->
<nav class="navbar bg-body-tertiary">
  <div class="container-fluid">
    <a class="navbar-brand" href="#">고객관리</a>
  </div>
</nav>
<!-- 폼페이지
요청URI : /cus/createPost
요청파라미터 : {cusNum=1234, cusNm=새롬이, postno=33233...}
요청방식 : post
 - modelAttribute="cusVO" => 컨트롤러에서 매게변수에 담아줬던 데이터를 연결해주는 것 
    꼭 이름을 같게 설정할 것
 -->
<form:form modelAttribute="cusVO" action="/cus/createPost" method="post">
<!-- 폼데이터 -->
<div class="bd-example">
	<div class="mb-3">
		<label for="cusNum" class="form-label">고객번호</label>
		<!--꺽음쇄form:input에는 type="text"랑 id="cusNum", name="cusNum", value가 내장 --> 
		<form:input class="form-control"
			path="cusNum" placeholder="고객번호를 입력해주세요" />
		<!-- path : cusVO객체의  cusNum 멤버변수 -->	
		<form:errors path="cusNum" style="color:red;" />
	</div>
	<div class="mb-3">
		<label for="cusNm" class="form-label">고객명</label> 
		<form:input class="form-control"
			path="cusNm" placeholder="고객명을 입력해주세요" />
		<form:errors path="cusNm" style="color:red;" />
	</div>
	<div class="mb-3">
		<div>
			<label for="postno" class="form-label">우편번호</label>
		</div>
		<div> 
			<input type="text" class="form-control"
				id="postno" name="postno" placeholder="우편번호를 입력해주세요"
				value="${cusVO.postno}"
				style="width:80%;float:left;" />
			<input class="btn btn-info" type="button" value="우편번호 검색"  disabled="disabled" 
				style="width:20%;float:right;" id="btnPostno" />
		</div>
	</div>
	<div class="mb-3">
		<label for="cusAddr" class="form-label">주소</label> 
		<input type="text" class="form-control"
			id="cusAddr" name="cusAddr" placeholder="주소를 입력해주세요" value="${cusVO.cusAddr}" />
	</div>
	<div class="mb-3">
		<label for="addrDet" class="form-label">상세 주소</label> 
		<input type="text" class="form-control"
			id="addrDet" name="addrDet" placeholder="상세 주소를 입력해주세요" value="${cusVO.addrDet}" />
	</div>
	<div class="mb-3">
		<label for="cusPhe" class="form-label">연락처</label> 
		<input type="text" class="form-control"
			id="cusPhe" name="" placeholder="연락처를 입력해주세요" value="${cusVO.cusPhe}" />
		<form:errors path="cusPhe" style="color:red;" />
	</div>
	<div class="mb-3">
		<label for="cusBir" class="form-label">생일</label> 
		<input type="text" class="form-control"
			id="cusBir" name="cusBir" placeholder="생일을 입력해주세요" 
			value="<fmt:formatDate pattern='yyyy-MM-dd' value='${cusVO.cusBir }'/>" />
		<form:errors path="cusBir" style="color:red;" />
	</div>
	<div class="mb-3">
		<label for="hobbyList" class="form-label">취미</label> 
		<form:checkbox path="hobbyList" value="Music" label="Music"/>
		<form:checkbox path="hobbyList" value="Movie" label="Movie"/>
		<form:checkbox path="hobbyList" value="Sports" label="Sports"/>
	</div>
	<div class="mb-3">
		<label for="gender" class="form-label">성별</label> 
		<form:radiobutton path="gender" value="male" label="male"/>
		<form:radiobutton path="gender" value="female" label="female"/>
		<form:radiobutton path="gender" value="others" label="others"/>
	</div>
	<div class="mb-3">
		<label for="nationality" class="form-label">국적</label> 
		<form:select path="nationality" items="${nationalityMap}" />
	</div>
	<div class="mb-3">
		<!-- 고객 : 소유 자동차(List<CarVO> carVOList  = 1 : N 
		name="carVOList[0].carNum"  : 중접된 자바빈 , list 의 객체의 멤버변수
		-->
		<div class="card" style="width: 100%;">
		  <div class="card-header">
		    소유자동차
		  </div>
		  <ul class="list-group list-group-flush">
		    <!-- 
		    cusVO : CustVO cusVO
		    cusVO.carVOList : List<CarVO> carVOList
		     -->
		<c:forEach var="carVO" items="${cusVO.carVOList}" varStatus="stat" >	  
		    <li class="list-group-item">
		    	<input type="hidden" name="carVOList[${stat.index}].cusNum" value="${carVO.cusNum}" />
		    	<input type="text" class="form-control" name="carVOList[${stat.index}].carNum"
		    		style="width:25%;float:left;" placeholder="자동차번호"
		    		 value="${carVO.carNum}" required/>
		    	<input type="text" class="form-control" name="carVOList[${stat.index}].mnfNum"
					style="width:25%;float:left;" placeholder="제조 번호"
					value="${carVO.mnfNum}" required />
		    	<input type="text" class="form-control" name="carVOList[${stat.index}].dt"
		    		style="width:25%;float:left;" placeholder="연식"
		    		value="<fmt:formatDate pattern='yyyy-MM-dd' value='${carVO.dt}' />"	 />
		    	<input type="text" class="form-control" name="carVOList[${stat.index}].dist"
		    		style="width:25%;float:left;" placeholder="주행거리"
		    		value="${carVO.dist}" />
		    </li>
		    </c:forEach>
		  </ul>
		</div>
	</div>
	<div class="mb-3">
		<button type="submit" class="btn btn-primary btn-lg">등록</button>
	</div>
</div>
</form:form>

 

 

SQL DEVELOPER

<데이터 딕셔너리 확인해보기>