Spring JDBC에는 DataSource 이니셜라이저 기능이 있습니다. Spring Boot는 기본적으로 이 기능을 활성화하고 표준 위치인 schema.sql 및 data.sql(클래스 경로의 루트)에서 SQL을 로드합니다.
관례적으로 데이터 정의어(DDL)는 schema.sql 파일에 작성하고 데이터 조작어(DML)은 data.sql 파일에 작성됩니다.
실행순서 : schema.sql
-> data.sql
미션에서
h2 in-memory Database
를 사용하고 있기 때문에 문제는 없었지만, 만약embedded
로 사용한다면schema.sql
과data.sql
가 스프링이 실행될때마다 실행할텐데 괜찮을까?
spring.h2.console.enabled=true
spring.sql.init.mode=always
spring.datasource.url=jdbc:h2:/Users/powermac/cartdb;MODE=MySQL
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=test
스프링의 경우 내장 데이터베이스(H2, HSQL, Derdy)에 대해서 스크립트 기반의 초기화를 기본적으로 실행하지만, 내장 데이터베이스가 아닌 경우 다음 옵션을 활성화(= always) 해야 한다.
// spring boot 2.4.x
spring.datasource.initialization-mode=always
// spring boot 2.5.x
spring.sql.init.mode=always
// script 파일이 hibernate 초기화 이후 동작하게 하기 위한 옵션
spring.jpa.defer-datasource-initialization=true
https://wildeveloperetrain.tistory.com/228
두번째 실행시켰을때 Table "ITEM" already exists;
테이블 중복 생성 오류가 발생한다.
spring.sql.init.mode=never
or
spring.sql.init.mode=embedded
never 옵션을 사용하면 더이상 sql script를 실행하지 않기 때문에 테이블 중복에러가 발생하지 않습니다.
CREATE TABLE IF NOT EXISTS item
(
id bigint PRIMARY KEY AUTO_INCREMENT NOT NULL,
name varchar(30) NOT NULL,
item_url text NOT NULL,
price int NOT NULL
);
INSERT IGNORE INTO item(name, item_url, price) values ('치킨', 'https://image.homeplus.kr/td/f42afe4b-e0a8-4c79-a07c-aaee40c93a57', 10000);
IF NOT EXISTS
, IGNORE
를 사용하면 테이블이나 데이터가 존재할경우 생성하지 않는다.
IGNORE
의 경우 mysql 문법이므로
spring.datasource.url=jdbc:h2:~/cartdb;MODE=MySQL
위 와 같이 MODE로 명시 해줘야한다.
[90020][90020] Database may be already in use: null. Possible solutions: close all other connection(s); use the server mode [90020-210] The file is locked: /Users/powermac/cartdb.mv.db [2.1.210/7].
여러 포트에서 동일한 앱을 실행하는 경우 AUTO_SERVER=TRUE다음과 같이 URL을 추가해야한다.
참조가 있는 테이블을 TRUNCATE
할때는
SET REFERENTIAL_INTEGRITY FALSE;
TRUNCATE TABLE cart RESTART IDENTITY;
TRUNCATE TABLE item RESTART IDENTITY;
TRUNCATE TABLE member RESTART IDENTITY;
SET REFERENTIAL_INTEGRITY TRUE;
위 와 같이 SET REFERENTIAL_INTEGRITY FALSE;
해야한다.