Spring 17 - 데이터베이스 구축부터 CRUD까지 (다음 우편번호 api 활용)
개념 설계 : 개체 - 관계 설정
개체
- 명사
- 핵심 개념
- 명확해야함
- 구별이 되어야함
데이터 베이스에서는 다대다 관계를 처리할 수 없다.
자료사전
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>
- button과 form태그를 만들어서 전송
- 오류처리를 위한 <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
- form: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){
// 우편번호
$("#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
<데이터 딕셔너리 확인해보기>