본문 바로가기
Programming/Spring

스프링부트 h2 설정

by peter paak 2020. 7. 8.
728x90

Embedded 데이터베이스

1. Dependency

build.gradle

runtimeOnly 'com.h2database:h2'

2. Configuration

application.yml

spring.h2.console.enabled: true

3. h2 접속

해당 주소로 h2 console에 접근합니다.

localhost:8080/h2-console

스프링부트는 내부적으로 아래와 같은 설정을 자동으로 합니다.
그러므로 화면과 똑같은 값이 있는지 확인하셔야 합니다.

  • Driver Class : org.h2.Driver
  • JDBC URL : jdbc:h2:mem:testdb
  • Username : sa
  • Password :

4. 로그 설정

application.yml

logging.level.org.hibernate.SQL: debug            # 로그 형식으로 쿼리 보여주기
spring.jpa.properties.hibernate.format_sql: true  # 압축된 쿼리를 읽기 좋게 포멧
spring.jpa.hibernate.ddl-auto: create             # 서버 시작에 테이블 생성

spring.jpa.hibernate.ddl-auto

  • create : 서버 시작에 모든 테이블 생성
  • create-drop : 서버 시작에 모든 테이블 생성, 서버 종료에 테이블 삭제
  • update : 서버 시작에 변경된 내용 반영. 테이블이 없으면 생성
  • validate : 서버 시작에 엔티티와 테이블 비교, 다르면 종료
  • none : 아무 처리하지 않음

build.gradle

implementation "com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.6.1"  // 쿼리의 실제 파라미터 보여주기

로컬에서 실행하기

1. 저장한 설정

저장한 설정을 Generice H2 (Server)로 변경한다. 이제 tcp 통신을 통해 로컬의 test라는 데이터베이스에 저장되게 된다

2. Mac 사용자의 경우

맥을 사용할 경우 test 데이터베이스가 없다는 에러가 생길 경우가 있습니다. 이는 MAC OS 버전이 Catalina인 경우 발생할 수 있습니다. 이 경우 JDBC URL을 jdbc:h2:~/test로 바꿔줍니다. 그리고 접속을 하면 /User/사용자/ 경로 아래 test 라는 데이터베이스가 생성됩니다. 재시작 이후 JDBC URL을 jdbc:h2:tcp://localhost/~/test로 바꾸면 사용가능 합니다.

참고. 발생 가능한 이슈

첫번째. Database "mem:testdb" not found, either pre-create it or allow remote database creation (not recommended in secure environments)

문제점
내용을 살펴보면 mem:testdb라는 데이터베이스를 찾을 수 없다고 나옵니다. 혹은 데이터베이스를 미리 생성(pre-create) 할 수도 없다고 나옵니다. 혹은 원격 데이터 생성도 할 수 없다고 나옵니다. 데이터베이스를 보안상의 이유로 생성을 못하게 h2 기본 설정 자체에서 막아놓을 것으로 보입니다.

원인
조금 찾아본 결과 이곳에서 문제의 원인을 찾을 수 있었습니다. h2가 1.4.1971.4.198버전 사이에 대규모 업데이트가 되면서 데이터베이스를 미리 생성하는 것을 방지하도록 설정되었습니다.

해결책

  1. h2의 버전을 1.4.198보다 낮은 버전으로 설정
runtimeOnly 'com.h2database:h2:1.4.197'
  1. 데이터베이스 생성
    기존에 생성해주는 데이터베이스가 없으므로 직접 데이터베이스를 생성할 수 있습니다. 해당 내용은 1.4.197 이하 버전에서는 스프링부트가 h2를 classpath에서 발견하면 자동적으로 설정되는 내용입니다. 그러므로 해당 버전을 사용한다면 아래 내용이 내부적으로 설정되어 있습니다.

application.yml

spring.datasource.url: jdbc:h2:mem:testdb
spring.datasource.driverClassName: org.h2.Driver
spring.datasource.username: sa
spring.datasource.password:
spring.jpa.database-platform: org.hibernate.dialect.H2Dialect

두번째. 403 forbidden

문제점
스프링 서큐리티를 사용할 때 403(접속 권한) 오류가 발생합니다.

원인
스프링 서큐리티에서 아래와 같은 내용을 설정해주셔야 합니다.

  • csrf disable
  • X-Frame-Options disable
  • /h2-console 허용

해결책

@EnableWebSecurity
@Configuration
public class OAuthConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .headers().frameOptions().disable()
                .and()
                .authorizeRequests()
                .antMatchers("/h2-console/**")
                .permitAll();
    }
}

인텔리제이에서 Datasource 연결

org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "CATALOGS" not found 에러

인텔리제이에서 h2 연결 시 발생하는 문제입니다.
현재 사용하는 h2는 2.1.214 (2022.11.3 최신버전)을 사용하면서 발생한 에러입니다.
원인을 검색하던 결과 이곳에서 해결법을 찾을 수 있었습니다

해당 이슈는 인텔리제이가 h2 접속시 초기 데이터를 fetch 하면서 발생하는 에러입니다

SELECT CATALOG_NAME FROM INFORMATION_SCHEMA.CATALOGS

하지만 해당 테이블은 h2 1.4.200 이하 버전에만 존재하는 테이블입니다.

이 경우 OLD_INFORMATION_SCHEMA=TRUE 옵션을 url 마지막에 붙혀주시면 됩니다

jdbc:h2:tcp://localhost/~/h2/2.1.214/db/test;OLD_INFORMATION_SCHEMA=TRUE

접속 이후 INFORMATION_SCHEMA 데이터베이스를 확인해보시면 CATALOGS 테이블이 존재함을 볼 수 있습니다

728x90