[ 스프링부트 / Spring Boot ] 2.5.x data.sql 문제 (h2, mysql)
백엔드/SpringBoot

[ 스프링부트 / Spring Boot ] 2.5.x data.sql 문제 (h2, mysql)

1. 문제 발생

온라인 강의를 듣는 중, data.sql을 만들어서 기초 데이터를 넣는 부분이 있었다.

같은 소스를 실행했는데, 문제가 발생하여 데이터가 입력되지 않고 에러가 발생했다.


2. 원인 파악

프로젝트 구성 및 테스트 코드

 

data.sql
call next value for hibernate_sequence;
insert into user (`id`, `name`, `email`, `created_at`, `updated_at`) values (1, 'martin', 'martin@fastcampus.com', now(), now());

call next value for hibernate_sequence;
insert into user (`id`, `name`, `email`, `created_at`, `updated_at`) values (2, 'dennis', 'dennis@fastcampus.com', now(), now());

call next value for hibernate_sequence;
insert into user (`id`, `name`, `email`, `created_at`, `updated_at`) values (3, 'sophia', 'sophia@slowcampus.com', now(), now());

call next value for hibernate_sequence;
insert into user (`id`, `name`, `email`, `created_at`, `updated_at`) values (4, 'james', 'james@slowcampus.com', now(), now());

call next value for hibernate_sequence;
insert into user (`id`, `name`, `email`, `created_at`, `updated_at`) values (5, 'martin', 'martin@another.com', now(), now());

첫번째, 실행해 본 결과 -> 에러 발생

아래와 같이 HIBERNATE_SEQUENCE 가 문제인 듯 싶어, 'call next value for hibernate_sequence;' 부분을 주석 처리

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSourceScriptDatabaseInitializer' defined in class path resource [org/springframework/boot/autoconfigure/sql/init/DataSourceInitializationConfiguration.class]: Invocation of init method failed; nested exception is org.springframework.jdbc.datasource.init.ScriptStatementFailedException: Failed to execute SQL script statement #1 of URL [file:/C:/Users/Sim/Desktop/folder/develop/_%ec%b4%88%ea%b2%a9%ec%9e%90%20%ea%b0%95%ec%9d%98/Part4/bookmanager/build/resources/test/data.sql]: call next value for hibernate_sequence; nested exception is org.h2.jdbc.JdbcSQLSyntaxErrorException: Sequence "HIBERNATE_SEQUENCE" not found; SQL statement: call next value for hibernate_sequence [90036-200]

 

두번째, 실행해 본 결과 

아래와 같이 USER 테이블이 생성되지 않았다하여 schema.sql도 생성

-> schema.sql을 통해 create table을 했지만 데이터가 생성되지 않음. 

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSourceScriptDatabaseInitializer' defined in class path resource [org/springframework/boot/autoconfigure/sql/init/DataSourceInitializationConfiguration.class]: Invocation of init method failed; nested exception is org.springframework.jdbc.datasource.init.ScriptStatementFailedException: Failed to execute SQL script statement #1 of URL [file:/C:/Users/Sim/Desktop/folder/develop/_%ec%b4%88%ea%b2%a9%ec%9e%90%20%ea%b0%95%ec%9d%98/Part4/bookmanager/build/resources/test/data.sql]: insert into user (`id`, `name`, `email`, `created_at`, `updated_at`) values (1, 'martin', 'martin@fastcampus.com', now(), now()); nested exception is org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "USER" not found; SQL statement: insert into user (`id`, `name`, `email`, `created_at`, `updated_at`) values (1, 'martin', 'martin@fastcampus.com', now(), now()) [42102-200]

3. 해결 방법

구글링을 하여, 검색하던 중 한 블로그를 발견하였고 원인을 찾았다.

Hibernate and data.sql
By default, data.sql scripts are now run before Hibernate is initialized. This aligns the behavior of basic script-based initialization with that of Flyway and Liquibase. If you want to use data.sql to populate a schema created by Hibernate, set spring.jpa.defer-datasource-initialization to true. While mixing database initialization technologies is not recommended, this will also allow you to use a schema.sql script to build upon a Hibernate-created schema before it’s populated via data.sql.

 

Spring Boot 2.5버전 부터는 data.sql 실행하려면 2가지 방법이 있다.

  1.  application.yml(또는 properties)에 spring.jpa.defer-datasource-initialization 옵션 값을 true로 추가
  2. schema.sql을 추가해서 hibernate 가 스키마를 생성하는 과정보다 먼저 실행되도록하여 해당 스키마에 data.sql을 채우도록하는 방법

(2번째 방법은 권장하지 않는 방법)

 

application.yml
spring:
  h2:
    console:
      enabled: true

  jpa:
    defer-datasource-initialization: true

data.sql이 잘 실행되어, 테스트 코드가 정상적으로 완료됐다.


Mysql에서 data.sql 읽는 방법

  • 스프링부트 2.4.x에선 spring.datasource.initialization.mode를 사용해서 data.sql, schema.sql을 실행
  • 스프링부트 2.5.x에선 spring.datasource.initialization.mode가 depreated로 표시
    - spring.sql.init.mode로 대체 sql관련 공통화 부분을 spring.sql로 따로 분리를 시킨게 요인 (spring2.5-release-note)
스프링부트 버전: 2.4.x
spring:
  ...
  
  datasource:
    url: jdbc:mysql://localhost:3306/book_manager
    username: root
    password: root
    initialization-mode: always
스프링부트 버전: 2.5.x
spring:
  ...
  
  datasource:
    url: jdbc:mysql://localhost:3306/book_manager
    username: root
    password: root
    
  sql:
    init:
      mode: always

 

 


참고 사이트: https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.5-Release-Notes

 

GitHub - spring-projects/spring-boot: Spring Boot

Spring Boot. Contribute to spring-projects/spring-boot development by creating an account on GitHub.

github.com

 

참고 블로그: https://velog.io/@khsb2012/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B6%80%ED%8A%B8-2.5-%EC%97%85%EB%8D%B0%EC%9D%B4%ED%8A%B8-hibernate-data.sql-%EA%B4%80%EB%A0%A8-%EB%B3%80%EB%8F%99%EC%82%AC%ED%95%AD

 

스프링 부트 2.5 업데이트 : hibernate, data.sql 관련 변동사항

spring boot 2.5 hibernate, data.sql 관련 변동사항 정리

velog.io