Language/Java

Spring Boot/어플리케이션 실행할때 JPA 스키마 생성 및 ddl, dml sql 실행

건담아빠 2022. 8. 18. 21:37

https://github.com/dchkang83/project-board

 

GitHub - dchkang83/project-board

Contribute to dchkang83/project-board development by creating an account on GitHub.

github.com

 

jpa의 ddl-auto: create 옵션 설정으로 entity구성을 생성하고 추가적인 ddl 및 dml 스크립트를 만들어 놓고 소스 수정이 발생해도 주요 데이터는 이미 넣어져 있는 형태로 구성할때 유요할 듯 하다. (저도 매번 귀찮아서.. 그냥 한번 설정해 주고 쓴다.)

 

JPA ddl-auto 설정

스프링부트 기동시에 선언되어 있는 entity속성에 맞게 테이블 생성/수정

spring:
  datasource:
    ...
  jpa:
    defer-datasource-initialization: true # Hibernate 초기화 후 data.sql 실행
    hibernate:
      ddl-auto: create #create update none
      naming:
        physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
    show-sql: true
...
Hibernate 초기화 후 data.sql을 실행하기 위해 defer-datasource-initialization: true 설정을 해준다.

 

JPA ddl 실행 후 sql 실행

각자의 환경에 맞게 ddl 및 dml sql 문을 작성하고 위치를 설정한다.

spring:
  datasource:
    ...
  jpa:
    ...
  sql:
    init:
      mode: always # 서버 시작시 항상 classpath의 sql문을 실행하도록 설정
      continue-on-error: false # 서버 시작시 sql문을 실행할 때 오류 무시하고 계속 진행
      data-locations: classpath:sql/data.sql # 서버 시작시 dml sql문을 실행할 위치 및 파일 지정
      # schema-locations: classpath:sql/schema.sql # 서버 시작시 ddl sql문을 실행할 위치 및 파일 지정
...

 

주요소스

Entity

public class User {
  @JsonIgnore // JSON으로 표현해줄때 제외한다
  @Id
  @Column(name = "user_no")
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private long userNo;

  @Column(name = "user_name", length = 50, unique = true)
  private String username;

  @JsonIgnore
  @Column(name = "password", nullable = false, length = 200)
  private String password;

  @ManyToMany
  @JoinTable(
     name = "t_user_authority",
     joinColumns = {@JoinColumn(name = "user_no", referencedColumnName = "user_no")},
     inverseJoinColumns = {@JoinColumn(name = "authority_name", referencedColumnName = "authority_name")})
  private Set<Authority> authorities;
}

@Entity
@Table(name = "t_authority")
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Authority {
  @Id
  @Column(name = "authority_name", length = 50)
  private String authorityName;
}

 

data.sql

INSERT INTO t_authority (`authority_name`) values ('ROLE_USER');
INSERT INTO t_authority (`authority_name`) VALUES ('ROLE_MANAGER');
INSERT INTO t_authority (`authority_name`) values ('ROLE_ADMIN');


INSERT INTO t_user (`user_name`, `password`) VALUES ('customer@naver.com', '$2a$10$rVT/tNSwxPt7j4eAI1NFrO8NA3JRnhvhyIIHQSdo.vusLrIBXFZ.6');
INSERT INTO t_user (`user_name`, `password`) VALUES ('admin@naver.com', '$2a$10$rVT/tNSwxPt7j4eAI1NFrO8NA3JRnhvhyIIHQSdo.vusLrIBXFZ.6');
INSERT INTO t_user (`user_name`, `password`) VALUES ('manager@naver.com', '$2a$10$rVT/tNSwxPt7j4eAI1NFrO8NA3JRnhvhyIIHQSdo.vusLrIBXFZ.6');


INSERT INTO t_user_authority (`user_no`, `authority_name`) VALUES (1, 'ROLE_USER');
INSERT INTO t_user_authority (`user_no`, `authority_name`) VALUES (2, 'ROLE_USER');
INSERT INTO t_user_authority (`user_no`, `authority_name`) VALUES (2, 'ROLE_MANAGER');
INSERT INTO t_user_authority (`user_no`, `authority_name`) VALUES (3, 'ROLE_USER');
INSERT INTO t_user_authority (`user_no`, `authority_name`) VALUES (3, 'ROLE_MANAGER');
INSERT INTO t_user_authority (`user_no`, `authority_name`) VALUES (3, 'ROLE_ADMIN');

 

짜잔... `ddl-auto: create` 옵션으로 인해 User 및 Authority entity들의 구성을 생성하고 `defer-datasource-initialization: true`

옵션 설정으로 인하여 어플리케이션 실행시점에 JPA의 entity에 선언된 ddl을 실행하고 INSERT 구문들이 실행됨으로써 어플리 케이션 실행과 동시에 DB 환경이 완성된다.