본문 바로가기
Spring|Spring-boot/Spring-Data-JPA

Initialize Database Using SQL Script in Spring Boot

by oncerun 2023. 6. 21.
반응형

Initialize a Database Using JPA

JPA에는 DDL 생성 속성이 존재한다. 엔티티에 매핑되는 테이블이 데이터베이스에 없는 경우 애플리케이션 초기화 단계에서 적절하게 테이블을 생성해 준다.

물론 종료 시 삭제, 업데이트, 아무런 일도 하지 않도록 설정할 수 있다.

 

spring.jpa.generate-ddl이라는 external properties을 통해 DDL 기능을 끄고 킬 수 있다.

spring.jpa.hibernate.ddl-auto (enum)은  다양한 행동을 지정한다. 

 

Spring boot는 내장 데이터베이스가 감지된 경우만 created-drop 옵션으로 동작합니다. 그 외에는 none으로 기본값을 가집니다.

 

이러한 schema creation을 활성화시키기 위해선 org.hibernate.SQL의 debug mode를 활성화하면 된다.

 

💡 JPA 구현체로 Hibernate를 사용하는 경우, root의 classpath에 있는 import.sql이라는 파일이 실행됩니다. 이는 spring과 관련 없는 기능입니다.

 

Initialize a Database Using Basic SQL Scripts

Spring Boot는 JDBC DataSoruce 또는 R2 DBC ConnectionFactory의 스키마를 자동으로 생성하고 이를 초기화할 수 있습니다. 이는 root classpath에 위치한 schema.sql, data.sql 로드하기 때문입니다.

기본적으로 데이터베이스 초기화는 임베디드 인메모리 데이터베이스를 사용할 때만 수행됩니다. 만약 유형에 관계없이 SQL 베이스를 항상 초기화하려면 다음 속성을 aways로 설정하면 됩니다.

spring.sql.init.mode=aways

or

spring.sql.init.mode=never

 

 💡 Spring Boot는 init 스크립트에서 오류 발생 시 애플리케이션이 동작되지 않습니다. 해당 속성을 변경하려면 spring.sql.init.continue-on-error 속성을 참고하세요

 

그럼 JPA generate-ddl 속성과 Spring sql init 중 어떠한 속성이 먼저 실행될까?

Script-based 데이터베이스 초기화는 기본적으로 JPA EntityManagerFactory Bean이 생성되기 이전에 수행됩니다.

그렇기에 schema.sql로 JPA 엔티티에 대한 스키마를 사전에 만들고 data.sql로 엔티티에 대한 데이터를 채울 수 있습니다.

 

기본적으로 데이터 초기화 스크립트의 혼용은 추천되지 않습니다.

 

스크립트 기반한 DataSoruce 초기화가 Hibernate에서 수행되는 스키마 생성을 기반으로 수행하도록 spring.jpa.defer-

datasoruce-initialization을 true로 설정하면 됩니다.

이렇게 하면 DataSoruce 초기화가 EntityManagerFactory 빈이 생성되고 초기화될 때까지 지연됩니다.

 

그런 다음 schema.sql을 사용하여 스키마를 생성하고 data.sql을 통해 스키마를 채울 수 있습니다.

 

💡 기본 schema.sql 및 data.sql 스크립트를 Flyway 또는 Liquibase와 함께 사용하는 것은 권장되지 않으며 향후 릴리스에서 지원이 제거될 예정입니다.

 

 

 

우선적인 내 목적은 schema.sql, data.sql을 사용하여 기본 데이터를 애플리케이션 초기화 시점에 생성하는 것이다.

메모리 데이터베이스라 애플리케이션 종료 시 데이터도 날아가니 빠르게 테스트할 수 있다.

 

 

1.schema.sql

DROP TABLE IF EXISTS worker;
create table worker  (
    id bigint not null,
    email varchar(255),
    image_url varchar(255),
    name varchar(255),
    video_url varchar(255),
    created_at timestamp,
    updated_at timestamp,
    primary key (id)
);

 

2.data.sql

INSERT INTO worker (id, name, email, image_url, video_url, created_at, updated_at)
VALUES (1, 'John', 'john@email.com', '/static/img/logo.jpg', '/static/video/1.mp4',
        CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);

INSERT INTO worker (id, name, email, image_url, video_url, created_at, updated_at)
VALUES (2, 'Alice', 'alice@email.com', '/static/img/logo.jpg', '/static/video/1.mp4',
        CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);

INSERT INTO worker (id, name, email, image_url, video_url, created_at, updated_at)
VALUES (3, 'Bob', 'bob@email.com', '/static/img/logo.jpg', '/static/video/1.mp4',
        CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);

INSERT INTO worker (id, name, email, image_url, video_url, created_at, updated_at)
VALUES (4, 'Eva', 'eva@email.com', '/static/img/logo.jpg', '/static/video/1.mp4',
        CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);

INSERT INTO worker (id, name, email, image_url, video_url, created_at, updated_at)
VALUES (5, 'Michael', 'michael@email.com', '/static/img/logo.jpg', '/static/video/1.mp4',
        CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);

INSERT INTO worker (id, name, email, image_url, video_url, created_at, updated_at)
VALUES (6, 'Sarah', 'sarah@email.com', '/static/img/logo.jpg', '/static/video/1.mp4',
        CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);

INSERT INTO worker (id, name, email, image_url, video_url, created_at, updated_at)
VALUES (7, 'David', 'david@email.com', '/static/img/logo.jpg', '/static/video/1.mp4',
        CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);

INSERT INTO worker (id, name, email, image_url, video_url, created_at, updated_at)
VALUES (8, 'Olivia', 'olivia@email.com', '/static/img/logo.jpg', '/static/video/1.mp4',
        CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);

INSERT INTO worker (id, name, email, image_url, video_url, created_at, updated_at)
VALUES (9, 'Daniel', 'daniel@email.com', '/static/img/logo.jpg', '/static/video/1.mp4',
        CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);

INSERT INTO worker (id, name, email, image_url, video_url, created_at, updated_at)
VALUES (10, 'James', 'james@email.com', '/static/img/logo.jpg', '/static/video/1.mp4',
        CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);

INSERT INTO worker (id, name, email, image_url, video_url, created_at, updated_at)
VALUES (11, 'Emily', 'emily@email.com', '/static/img/logo.jpg', '/static/video/1.mp4',
        CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);

 

3.application.yml

spring:
  profiles:
    include: oauth2, logging
  datasource:
    url: jdbc:h2:mem:testdb
    username: sa
    password:
  jpa:
    open-in-view: false
    properties:
      hibernate:
        format_sql: true
        jdbc:
          batch_size: 100
    show-sql: true

    hibernate:
      ddl-auto: none
    generate-ddl: false

  h2:
    console:
      enabled: true
      path: /h2-console
      
      

logging:
  level:
    org.hibernate.SQL: DEBUG
    org.hibernate.type.descriptor.sql.BasicBinder: TRACE
    org.springframework.web: DEBUG
반응형

'Spring|Spring-boot > Spring-Data-JPA' 카테고리의 다른 글

Projections  (1) 2022.12.03
스프링 데이터 JPA 구현체를 알아보자.  (0) 2022.12.03
도메인 컨버터 & 페이징과 정렬  (0) 2022.12.03
Auditing  (0) 2022.11.30
Custom Repository  (0) 2022.11.30

댓글