- 테이블 설계 완료 후 테이블 컬럼등 테이블 설계에 변동이 생기는 경우 DTO가 변경되며 전체적인 프로젝트에 차질이 생긴다
💡 추후에 변동이 없도록 설계시 최대한 꼼꼼하게 생성해야 한다- 최종목표는 오라클에서 코드를 입력하여 테이블 생성하는것이 아닌
Spring에서 테이블 생성 후 SQLDDL 코드를 가져와 바로 테이블 생성하는 것!
VScode 에서 ERD설계 extension 파일 생성 및 실행
Database 생성시 Oracle 선택
식당테이블 = 정적인 테이블
- 테이블 생성 후 SQLDDL 확인해보면
자동으로 SQL이 생성된 것을 확인 할 수 있다
식당 이미지 테이블 = 정적인 테이블
- BLOB ⇒ 바이너리
- 외래키 생성
하나의 식당은 여러개의 이미지를 가질 수 있다
➡️ 식당 테이블과 식당 이미지 테이블의 관계는1:N
테이블 생성 후 SQLDDL 확인
➡️ 외래키가 테이블 생성 시 추가된게 아닌, 테이블 생성 후 추가 된것을 알 수 있다
메뉴 테이블 = 정적인 테이블
- 외래키 생성
하나의 식당은 여러개의 메뉴를 가질 수 있다
➡️ 식당 테이블과 메뉴 테이블의 관계는1:N
고객 테이블 = 정적인 테이블
고객 테이블은 이전에 생성된 테이블과는 아무 관계가 없다
주문 행위가 일어나야 다른테이블과 관계가 생김
주문테이블 =동적인 테이블
- 테이블 생성시 수량 컬럼을 안 넣어도 된다
수량 1개당 주문 1개라고 처리되는 경우 추후에 통계에 사용하기 쉽다
하지만 수량이 많아지면 복잡하니 일단 수량 생성하여 사용해보기- 주문테이블은
고객 테이블
과메뉴 테이블
2개의 외래키를 가지며
정적인 두 테이블을 이어주는 동적인 테이블이다
- 하나의 고객은 여러개의 주문 가능
➡️ 고객 테이블과 주문 테이블의 관계는1:N
- 하나의 메뉴는 여러개의 주문이 가능하다
➡️ 메뉴 테이블과 주문 테이블의 관계는1:N
유료 프로그램의 경우 테이블 생성시 SQL간 테이블 생성하면 코드 이동,
코드 이동하면 테이블 생성이 되는 경우가 대부분이다
지금은 수동으로 이동하기!
시퀀스는 수동입력 해야한다
VScode에서 생성된 SQLDDL 가져와서 실행
🤯 오류
외래키명이 Oracle에서 기본제공하는 크기보다 큰 경우 지정한 외래키명을 사용 불가할 수도 있다
CREATE TABLE CUSTOMERTBL
(
PHONE VARCHAR2(20) NOT NULL,
ADDRESS VARCHAR2(100),
REGDATE TIMESTAMP DEFAULT CURRENT_DATE,
CONSTRAINT PK_CUSTOMERTBL PRIMARY KEY (PHONE)
);
COMMENT ON TABLE CUSTOMERTBL IS '고객테이블';
COMMENT ON COLUMN CUSTOMERTBL.PHONE IS '연락처';
COMMENT ON COLUMN CUSTOMERTBL.ADDRESS IS '주소';
COMMENT ON COLUMN CUSTOMERTBL.REGDATE IS '등록일자';
CREATE TABLE MENUORDERTBL
(
NO NUMBER NOT NULL,
CNT NUMBER ,
REGDATE TIMESTAMP DEFAULT CURRENT_DATE,
MENUNO NUMBER NOT NULL,
CUSTOMERID VARCHAR2(20) NOT NULL,
CONSTRAINT PK_MENUORDERTBL PRIMARY KEY (NO)
);
COMMENT ON TABLE MENUORDERTBL IS '메뉴주문테이블';
COMMENT ON COLUMN MENUORDERTBL.NO IS '주문테이블';
COMMENT ON COLUMN MENUORDERTBL.CNT IS '주문수량';
COMMENT ON COLUMN MENUORDERTBL.REGDATE IS '주문일자';
COMMENT ON COLUMN MENUORDERTBL.MENUNO IS '메뉴번호';
COMMENT ON COLUMN MENUORDERTBL.CUSTOMERID IS '연락처';
CREATE TABLE MENUTBL
(
NO NUMBER NOT NULL,
NAME VARCHAR2(100),
PRICE NUMBER ,
REGDATE TIMESTAMP DEFAULT CURRENT_DATE,
code VARCHAR2(20) NOT NULL,
CONSTRAINT PK_MENUTBL PRIMARY KEY (NO)
);
COMMENT ON TABLE MENUTBL IS '메뉴테이블';
COMMENT ON COLUMN MENUTBL.NO IS '메뉴번호';
COMMENT ON COLUMN MENUTBL.NAME IS '메뉴명';
COMMENT ON COLUMN MENUTBL.PRICE IS '메뉴가격';
COMMENT ON COLUMN MENUTBL.REGDATE IS '등록일';
COMMENT ON COLUMN MENUTBL.code IS '식당코드';
CREATE TABLE RESTAURANTIMAGETBL
(
NO NUMBER NOT NULL,
IMAGENAME VARCHAR2(100),
INAGETYPE VARCHAR2(20) ,
IMAGESIZE NUMBER ,
IMAGEDATA BLOB ,
REGDATE TIMESTAMP DEFAULT CURRENT_DATE,
code VARCHAR2(20) NOT NULL,
CONSTRAINT PK_RESTAURANTIMAGETBL PRIMARY KEY (NO)
);
COMMENT ON TABLE RESTAURANTIMAGETBL IS '식당이미지테이블';
COMMENT ON COLUMN RESTAURANTIMAGETBL.NO IS '이미지번호';
COMMENT ON COLUMN RESTAURANTIMAGETBL.IMAGENAME IS '이미지이름';
COMMENT ON COLUMN RESTAURANTIMAGETBL.INAGETYPE IS '이미지타입';
COMMENT ON COLUMN RESTAURANTIMAGETBL.IMAGESIZE IS '이미지크기';
COMMENT ON COLUMN RESTAURANTIMAGETBL.IMAGEDATA IS '이미지데이터';
COMMENT ON COLUMN RESTAURANTIMAGETBL.REGDATE IS '등록일';
COMMENT ON COLUMN RESTAURANTIMAGETBL.code IS '식당코드';
CREATE TABLE RESTAURANTTBL
(
code VARCHAR2(20) NOT NULL,
name VARCHAR2(50) ,
phone VARCHAR2(20) ,
address VARCHAR2(200),
regdate TIMESTAMP DEFAULT CURRENT_DATE,
CONSTRAINT PK_RESTAURANTTBL PRIMARY KEY (code)
);
COMMENT ON TABLE RESTAURANTTBL IS '식당테이블';
COMMENT ON COLUMN RESTAURANTTBL.code IS '식당코드';
COMMENT ON COLUMN RESTAURANTTBL.name IS '식당이름';
COMMENT ON COLUMN RESTAURANTTBL.phone IS '연락처';
COMMENT ON COLUMN RESTAURANTTBL.address IS '주소';
COMMENT ON COLUMN RESTAURANTTBL.regdate IS '등록일';
ALTER TABLE RESTAURANTIMAGETBL
ADD CONSTRAINT FK_RESTAURANTTBL_TO_RESTAURANTIMAGETBL
FOREIGN KEY (code)
REFERENCES RESTAURANTTBL (code);
ALTER TABLE MENUTBL
ADD CONSTRAINT FK_RESTAURANTTBL_TO_MENUTBL
FOREIGN KEY (code)
REFERENCES RESTAURANTTBL (code);
ALTER TABLE MENUORDERTBL
ADD CONSTRAINT FK_MENUTBL_TO_MENUORDERTBL
FOREIGN KEY (MENUNO)
REFERENCES MENUTBL (NO);
ALTER TABLE MENUORDERTBL
ADD CONSTRAINT FK_CUSTOMERTBL_TO_MENUORDERTBL
FOREIGN KEY (CUSTOMERID)
REFERENCES CUSTOMERTBL (PHONE);
maven 으로 생성해 주어야 배포가 쉽다!
<dependencies>
<!-- tomcat embedded was -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
# 서버주소
# 127.0.0.1:8080/BOOT1/
server.port=8080
# 나중에 프로젝트시 여러명 사용시에는 여러개 서버 생성해준다
# server.servlet.context-path=/BOOT2
server.servlet.context-path=/BOOT1
# 소스코드 변경시 자동으로 서버 구동하기
spring.devtools.livereload.enabled=true
# view에 해당하는 html의 위치설정
# cache=false 개발시, 서비스 배포시에는 true
spring.thymeleaf.cache=false
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
package com.example.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class HomeController {
// 아래 4개의 주소는 모두 같다
// 크롬에서 127.0.0.1:8080/BOOT1
// 크롬에서 127.0.0.1:8080/BOOT1/
// 크롬에서 127.0.0.1:8080/BOOT1/home
// 크롬에서 127.0.0.1:8080/BOOT1/home.do
@GetMapping(value = {"/", "/home", "/home.do"})
public String homeGET(){
return "home";
}
}
<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>홈화면</title>
</head>
<body>
홈화면
</body>
</html>
➡️ 크롬에서 127.0.0.1:8080/BOOT1
package com.example.boot_20220915;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
// 서비스, 컨트롤러, 환경설정
@ComponentScan(basePackages = {
"com.example.service",
"com.example.controller"
})
@SpringBootApplication
public class Boot20220915Application {
public static void main(String[] args) {
SpringApplication.run(Boot20220915Application.class, args);
}
}