h2 Database 초기화 전략

Jae-Baek Song·2023년 5월 1일
0

스프링

목록 보기
9/10

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.sqldata.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; 테이블 중복 생성 오류가 발생한다.


해결법 1.

spring.sql.init.mode=never
or
spring.sql.init.mode=embedded

never 옵션을 사용하면 더이상 sql script를 실행하지 않기 때문에 테이블 중복에러가 발생하지 않습니다.


해결법 2.

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로 명시 해줘야한다.


H2 Database를 사용하면서 생긴 문제

h2 여러 포트에서 동일한 앱을 실행

[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].

https://stackoverflow.com/questions/8158969/h2-database-error-database-may-be-already-in-use-locked-by-another-process

여러 포트에서 동일한 앱을 실행하는 경우 AUTO_SERVER=TRUE다음과 같이 URL을 추가해야한다.


참조 테이블 TRUNCATE

참조가 있는 테이블을 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;
해야한다.

0개의 댓글