데이터베이스

[DB] Error / engine[*]=InnoDB"; expected "identifier";]

syj0522 2024. 11. 24. 16:00

Spring Boot 환경에서 In-memory h2를 사용하던 중 에러가 발생했다.

에러

더보기

    create table `bookmark` (
        `bookmark_id` integer not null auto_increment,
        `created_date` varchar(255) not null,
        `last_modified_date` varchar(255) not null,
        `name` varchar(255),
        `user_id` bigint,
        primary key (`bookmark_id`)
    ) engine=InnoDB

    create table `bookmark` (
        `bookmark_id` integer not null auto_increment,
        `created_date` varchar(255) not null,
        `last_modified_date` varchar(255) not null,
        `name` varchar(255),
        `user_id` bigint,
        primary key (`bookmark_id`)
    ) engine=InnoDB;
2024-11-25T01:34:30.307+09:00  WARN 35268 --- [cowshed] [           main] o.h.t.s.i.ExceptionHandlerLoggedImpl     : GenerationTarget encountered exception accepting command : Error executing DDL "
    create table `bookmark` (
        `bookmark_id` integer not null auto_increment,
        `created_date` varchar(255) not null,
        `last_modified_date` varchar(255) not null,
        `name` varchar(255),
        `user_id` bigint,
        primary key (`bookmark_id`)
    ) engine=InnoDB" via JDBC [Syntax error in SQL statement "\000d\000a    create table `bookmark` (\000d\000a        `bookmark_id` integer not null auto_increment,\000d\000a        `created_date` varchar(255) not null,\000d\000a        `last_modified_date` varchar(255) not null,\000d\000a        `name` varchar(255),\000d\000a        `user_id` bigint,\000d\000a        primary key (`bookmark_id`)\000d\000a    ) engine[*]=InnoDB"; expected "identifier";]

org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL "
    create table `bookmark` (
        `bookmark_id` integer not null auto_increment,
        `created_date` varchar(255) not null,
        `last_modified_date` varchar(255) not null,
        `name` varchar(255),
        `user_id` bigint,
        primary key (`bookmark_id`)
    ) engine=InnoDB" via JDBC [Syntax error in SQL statement "\000d\000a    create table `bookmark` (\000d\000a        `bookmark_id` integer not null auto_increment,\000d\000a        `created_date` varchar(255) not null,\000d\000a        `last_modified_date` varchar(255) not null,\000d\000a        `name` varchar(255),\000d\000a        `user_id` bigint,\000d\000a        primary key (`bookmark_id`)\000d\000a    ) engine[*]=InnoDB"; expected "identifier";]
at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:94) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.applySqlString(AbstractSchemaMigrator.java:575) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.applySqlStrings(AbstractSchemaMigrator.java:515) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.createTable(AbstractSchemaMigrator.java:315) ~

...

원인

1. engine=InnoDB;

 

h2가 이 명령어를 이해하지 못해서 발생한 에러이다. MySQL과 관련된 명령어이기 때문이다. 

자세히는 MySQL의 스토리지 엔진으로 InnoDB를 선택한다는 의미인데, h2는 스토리지 엔진이 하나밖에 없어서 선택할 수 없다. 

h2 모드로 ddl을 생성하도록 설정파일을 수정해야 한다.

 

2. test용 yaml 파일 인식 불가

 

나는 테스트 환경에서만 인메모리 h2를 사용하기 위해 테스트용 yaml파일을 따로 생성했다.

위치는 src/test/resources/이고 설정 파일을 테스트 클래스에 적용하기 위해 @TestPropertySource를 사용했다.

그런데 main의 classpath에 있는 yaml파일이 인식되고 있었다.

@TestPropertySource(locations = "classpath:application-test.yaml")
class QueryDslEventRepositoryTest {
	//...
}

 

해결

1. engine=InnoDB를 없애기 위해 url 끝에 MODE=MySQL을 제거하고, h2 Dialect를 추가해주었다. 

spring:

  config:
    active:
      on-profile: test

  datasource:
    url: jdbc:h2:mem:testdb #(1)
    driverClassName: org.h2.Driver
    username: sa
    password:

  jpa:
    hibernate:
      ddl-auto: update
    database-platform: org.hibernate.dialect.H2Dialect #(2)
    properties:
      hibernate:
        globally_quoted_identifiers: true
    show-sql: true

logging:
  level:
    org.springframework.orm.jpa: DEBUG
    org.springframework.transaction: DEBUG

 

2. 

main용, test용 yaml파일에 각각 profile을 설정해서 @ActiveProfiles로 yaml을 적용시켜주었다.

참고로 main의 yaml파일에 profile을 설정하는 방법이 현재 Spring Boot 버전과 맞지 않아서 마이그레이션시켜주었다.

#as-is
spring:
  profiles:
    active: local

#to-be
spring:
  config:
    activate:
      on-profile: "local"
@ActiveProfiles("test")
class QueryDslEventRepositoryTest {
	//...
}

 

 

https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-Config-Data-Migration-Guide

https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/