글 작성자: beaniejoy

Spring Boot로 개발할 때 간편하게 이용할 수 있는 h2 database에 대한 설정 내용을 기록하고자 합니다. 그 과정에서 에러 발생 및 처리에 대해서도 기록하고자 합니다.

해당 설정 내용은 github repository에서 확인할 수 있습니다.
(Github Repo)

 

GitHub - beaniejoy/test-project-repository: 🧪 Study & Test Repository, which manages and tests various frameworks, libraries

🧪 Study & Test Repository, which manages and tests various frameworks, libraries and modules, that consists of directories named by each topic. - GitHub - beaniejoy/test-project-repository: 🧪 S...

github.com

 

  • 프로젝트 기본 설정
    - build.gradle 설정
    - application.yml
  • Error Handling
    -MySQL 방언 설정 관련
    -ddl-auto 관련

 

📌1. 프로젝트 기본 설정

build.gradle 설정

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    compileOnly 'org.projectlombok:lombok'
    runtimeOnly 'com.h2database:h2'
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

h2 설정을 위해 기본적인 h2 의존성과 jpa starter, lombok 의존성을 추가했습니다.

application.yml

spring:
  datasource:
    url: jdbc:h2:mem:testdb;
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true
    properties:
      hibernate:
        format_sql: true
        dialect: org.hibernate.dialect.MySQL5InnoDBDialect
  h2:
    console:
      enabled: true
  • url: 위 내용은 memory 형태의 h2 db를 사용하기 위한 url 설정입니다.
    메모리형태로 h2를 사용하게 되면 애플리케이션을 종료하게 될 때 h2 안의 모든 데이터가 삭제됩니다. (주의)
  • ddl-auto: 여기서는 update로 설정했습니다. (뒤에 추가 설명)
    ddl-auto에는 create, create-drop, update, validate, none 등의 옵션이 있는데 설정에 따라 각각 다르게 작동합니다.
  • show-sql: jpa 관련 sql 쿼리를 보여주는 설정
  • format\_sql: true로 설정하면 sql에 대한 formatting을 해서 콘솔에 보여줍니다. 쿼리 보기가 편합니다.
  • dialect: hibernate에서 지원하는 특정 DB 방언을 설정하면 해당 방언으로 쿼리를 보여줍니다.

하지만 이렇게만 설정하고 Entity 클래스를 설정해서 애플리케이션을 실행하면 여러 에러가 발생하면서 실행종료 됩니다.

 

📌 2. Error Handling

MySQL 방언 설정 관련

GenerationTarget encountered exception accepting command : Error executing DDL...
org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL...
...
Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Syntax error in SQL statement...

위의 설정만 가지고 애플리케이션을 실행하면 위의 에러가 발생합니다. 정확하진 않지만 MySQL 방언을 hibernate에 등록했는데 이를 h2에서 인식을 못하는 것 같습니다.

spring:
  datasource:
    url: jdbc:h2:mem:testdb;MODE=MySQL

yml 설정에서 connection url에 testdb 뒤에 MODE=MySQL을 추가해줍니다. 그리고 다시 실행하면 잘 동작하는 것을 확인할 수 있습니다.

 

ddl-auto 관련

spring:
  jpa:
    hibernate:
      ddl-auto: create (update, create-drop, ...)

ddl-auto 설정은 애플리케이션 시작과 종료시 ddl 쿼리 생성 및 수행과 관련된 설정입니다. 저는 메모리 상태의 h2를 사용하기 때문에 따로 ddl-auto에 대한 설정은 필요가 없습니다. 위의 설정을 주석처리하고 애플리케이션을 실행해보면 실행은 잘되지만 실행 중간 단계에서 에러가 발생하고 있음을 알 수 있습니다.

보면 애플리케이션 실행 시 @Entity로 설정된 클래스들의 정보를 가지고 ddl 쿼리를 작성하게 되는데요. 중요한 것은 create 쿼리 전에 각 테이블에 대한 drop 처리를 진행합니다.

cafe_menu에 대해서 drop 하기 전에 연관관계 설정에 대해서 먼저 foreign key 제거를 하려는 과정에서 에러가 발생합니다.

Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "CAFE_MENU" not found; SQL statement:

당연하게도 cafe_menu 테이블 자체가 없기 때문에 cafe_menu의 연관과계를 삭제하려고 하는 것 자체가 모순이 됩니다.

애플리케이션 실행 자체는 잘 될지 몰라도 이러한 에러를 중간에 본다면 보기 좋지는 않네요.

 

spring:
  jpa:
    hibernate:
      ddl-auto: update

ddl-auto를 update로 설정합니다. 애플리케이션 실행시 변경 사항에 대해서만 ddl 쿼리를 수행하게 됩니다. 메모리 상태의 h2는 애초에 아무것도 없는 상태에서 시작하기 때문에 @Entity로 설정했던 모든 테이블 사항이 신규대상입니다. 그래서 따로 drop을 진행하지 않고 create만 수행하는 것을 볼 수 있습니다.

바로 create 쿼리 실행

참고로 ddl-auto를 create로 설정시 애플리케이션 실행하면 drop 후 create를 진행하게 됩니다. 결국 위의 에러 상황과 똑같은 상황이 발생하게 됩니다.

 

위의 내용은 메모리 상태의 h2에서 진행한 것들입니다. 메모리 상태가 아닌 실제 db를 connect한다면 위의 설정 내용과 완전히 다른 방식으로 접근해야 될 것입니다.