스프링부트 2.5+, Hibernate 사용시 DB 초기화 이슈

스프링부트 2.5+, Hibernate 사용시 DB 초기화 이슈

스프링부트 버전업에 의한 이슈 정리


🚨 문제


학습 프로젝트 진행 중 발견한 이슈이다.


  1. Hiberate를 사용하고 있었음
  2. 스프링부트 버전 2.4 대에서 2.5+ 이상으로 버전업
  3. data.sql이 아래와 같은 메시지와 함께 정상동작하지 않음


image


🚧 원인


스프링부트 📜 릴리즈노트 에서 찾았다.


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


대략 스프링부트 2.5부터는 data.sqlHibernate가 실행하는 ddl-auto 보다 먼저 실행된다는 것 같다.

따라서 기존과 같이 사용하고 싶다면 spring.jpa.defer-datasource-initialization=true 옵션을 추가하라고 한다.


실제로 이것이 문제인게 맞는지 우선 버전을 변경해 테스트해보았다.


우선 데모 프로젝트를 2.4.3 버전으로 생성했다.

의존성은 아주 간단하게 web, data-jpa, h2만 추가했다.


버전2 4 3


그리고 application.yaml 파일을 다음과 같이 설정했다.


# file: 'application.yaml'
spring:
  h2:
    console:
      enabled: true
      settings:
        web-allow-others: true

  datasource:
    url: jdbc:h2:mem:testdb
    username: sa
    password:

  jpa:
    properties:
      hibernate:
        format_sql: true
    hibernate:
      ddl-auto: create-drop


그리고 Hibernate가 테이블을 생성하도록 다음과 같이 간단한 엔티티 클래스를 작성했다.


@Entity
public class Member implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    private int age;

}


마지막으로 Hibernate가 생성한 테이블에 삽입될 데이터를 resources/data.sql에 추가했다.

-- file: 'resources/data.sql'
insert into member (name, age)
values ('name1', 10);

insert into member (name, age)
values ('name2', 10);


그리고 프로젝트를 실행하고 localhost:8080/h2-console로 접근하여 테이블이 정상적으로 생성되었는지, 데이터가 정상적으로 삽입되었는지를 확인했다.


image


버전을 내려서 진행하니 정상적으로 동작함을 확인했다.


✅ 해결


2.4대에서 2.5+이상의 버전으로 변경 할 경우 옵션을 줘야한다고 하니 데모 프로젝트의 스프링부트 버전을 2.6.1로 변경하고, application.yaml에 옵션을 추가했다.


image


# file: 'application.yaml'
spring:
  h2:
    console:
      enabled: true
      settings:
        web-allow-others: true
  datasource:
      url: jdbc:h2:mem:testdb
      username: sa
      password:
  jpa:
    defer-datasource-initialization: true # 추가 !
    properties:
      hibernate:
        format_sql: true
    hibernate:
      ddl-auto: create-drop


마찬가지로 프로젝트를 실행하고 localhost:8080/h2-console로 접근하여 테이블이 정상적으로 생성되었는지, 데이터가 정상적으로 삽입되었는지를 확인했다.


image


아무런 문제 없이 정상적으로 동작함을 확인했다.



© 2022. All rights reserved.