[Spring Boot #25] 스프링 부트 데이터베이스 초기화

이전 포스팅에서 쓰던 테스트 및 소스 코드를 사용합니다.


[Spring/Spring Boot] - [Spring Boot #24] 스프링 부트 Spring-Data-JPA 연동



| 스프링 부트 데이터베이스 초기화


실제 인메모리 DB가 아닌 일반 디스크 기반 DB에서는 Spring-Data-JPA에 의해 생성된 테이블과 데이터는 초기화되지 않고 디스크에 저장됩니다.

만일 실제 개발 혹은 배포 전에 실제 테스트를 하기 위한 목적으로 데이터 베이스를 자동적으로 초기화 하고자 한다면 그에 관련된 설정을 따로 스프링 부트 설정파일에 명시해야합니다.


| 데이터베이스 초기화 설정 파일

# application.properties
spring.datasource.hikari.maximum-pool-size=4

spring.datasource.url=jdbc:postgresql://localhost:5432/springboot
spring.datasource.username=saelobi
spring.datasource.password=pass

# 드라이버가 createClub을 지원하지 않아서 warning 뜨는 것을 방지
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true

spring.jpa.hibernate.ddl-auto=update
spring.jpa.generate-ddl=true
spring.jpa.show-sql=true

  • spring.jpa.hibernate.dll-auto : create, create-drop, update, validate, none 옵션을 설정할 수 있습니다. 
    1. create : JPA가 DB와 상호작용할 때 기존에 있던 스키마(테이블)을 삭제하고 새로 만드는 것을 뜻합니다.
    2. create-drop : JPA 종료 시점에 기존에 있었던 테이블을 삭제합니다.
    3. update : JPA에 의해 변경된 부분만 반영합니다.
    4. validate : 엔티티와 테이블이 정상 매핑되어 있는지만 검증합니다.
    5. none : 초기화 동작을 사용하지 않습니다.
  • spring.jpa.generate-dll: spring.jpa.hibernate.dll-auto 옵션을 사용할 것인지를 결정하는 프로퍼티입니다. 기본적으로 false로 되어있기 때문에 JPA에 의한 데이터베이스 자동 초기화 기능을 사용하려면 true로 세팅해야합니다.
  • spring.jpa.show-sql: JPA가 생성한 SQL문을 보여줄 지에 대한 여부를 알려주는 프로퍼티입니다.

update 옵션 설정 시 다음과 같이 SQL문이 자동적으로 실행되는 것을 볼 수 있습니다.

Hibernate: alter table if exists public.account add column password varchar(255)
Hibernate: alter table if exists public.account add column username varchar(255)
Hibernate: create sequence hibernate_sequence start 1 increment 1


만일 create 옵션 설정 시 테이블을 drop하고 다시 생성하는 SQL문이 실행되는 것을 볼 수 있습니다.

Hibernate: drop table if exists account cascade
Hibernate: drop sequence if exists hibernate_sequence
Hibernate: create sequence hibernate_sequence start 1 increment 1
Hibernate: create table account (id int8 not null, password varchar(255), username varchar(255), primary key (id))


이번에는 validate옵션을 줘서 엔티티와 해당 매핑하려는 테이블이 제대로 매핑됬는 지 체크하려고 합니다.

spring.jpa.hibernate.ddl-auto=validate
spring.jpa.generate-ddl=false
spring.jpa.show-sql=true


만일 다음과 같은 스키마를 지닌 테이블이 있을 경우

springboot=# select * from account;
id | password | username
----+----------+----------


이 테이블과 매핑하려는 엔티티가 이 테이블과 맞지 않을 경우 에러를 발생하게 됩니다.  

@Entity
public class Account {

@Id
@GeneratedValue
private Long id;

private String username;

private String password;

// 테이블에는 email이란 컬럼이 없으므로 유효하지 않음
private String email;

public String getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Account account = (Account) o;
return Objects.equals(id, account.id) &&
Objects.equals(username, account.username) &&
Objects.equals(password, account.password);
}

@Override
public int hashCode() {
return Objects.hash(id, username, password);
}
}
2019-01-10 23:47:02.160 ERROR 16140 --- [           main] o.s.boot.SpringApplication               : Application run failed

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.tool.schema.spi.SchemaManagementException: Schema-validation: missing column [email] in table [account]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1745) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:576) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCap


이제 다음과 같이 update로 설정값을 변경하고 다시 어플리케이션을 실행하게 되면 엔티티 소스코드 상에서 추가되었던 email 변수가 그대로 테이블에 반영되는 것을 볼 수 있습니다.

spring.jpa.hibernate.ddl-auto=update
spring.jpa.generate-ddl=true
spring.jpa.show-sql=true
Hibernate: alter table if exists public.account add column email varchar(255)
springboot=# select * from account;
id | password | username | email
----+----------+----------+-------


참고로 엔티티의 변수명을 바꾸더라도 JPA가 해당 테이블의 컬럼명을 자동적으로 업데이트 해주지 않습니다.


| SQL 스크립트 파일을 통한 초기화 방법


schema.sql 혹은 schema-${platform}.sql을 다음과 같이 추가하여 데이터베이스를 자동적으로 초기화 할 수 있습니다.

-- schema.sql
drop table account if exists
drop sequence if exists hibernate_sequence
create sequence hibernate_sequence start with 1 increment by 1
create table account (id bigint not null, email varchar(255), password varchar(255), username varchar(255), primary key (id))


spring.jpa.hibernate.dll-auto를 validate로 정의해도 스프링 부트에서 자동적으로 schema.sql의 SQL문을 실행하기 때문에 자동적으로 테이블이 삭제되었다가 생성됩니다.

spring.jpa.hibernate.ddl-auto=validate
spring.jpa.generate-ddl=false
spring.jpa.show-sql=true


만일 schema-$(platform),sql 형식으로 파일을 바꿀 시에는 ${platform}값에 해당하는 설정값을 설정파일에 명시해야 합니다.

spring.datasource.platform=postgresql


만일 다시 테이블 초기화 시 같이 삽입하고 싶은 데이터가 있으면 data.sql 혹은 data-${platform}.sql에 insert문을 작성하면 됩니다. 

-- data.sql
insert into account(id, password, username, email) values ('1', 'pass', 'saelobi', 'engkimbs@gmail.com')


참고자료 : https://www.inflearn.com/course/스프링부트


이 글을 공유하기

댓글(0)

Designed by JB FACTORY