SprongBoot DbInit 설정방법 (@PostConstruct, CommandLineRunner, schema.sql)

devdo·2023년 10월 3일
0

SpringBoot

목록 보기
38/40
post-thumbnail

처음 SpringBoot 어플리메이션을 실행시, DB 데이터를 미리 insert 하는 작업을 할시,
SpringBoot에서 할 수 있는 대표적인 3가지를 소개합니다.

개인적으로, @PostConstruct를 더 추천합니다!
🌟 2) CommandLineRunner 를 주로 사용


1) @PostConstruct

@Slf4j
@Component
@Profile("test")
@RequiredArgsConstructor
public class TestDataInit {

    private final CouponRepository couponRepository;

    /**
     * 테스트용 데이터 추가
     */
    @PostConstruct
    public void init() {
        log.info("test data init run...");
        LongStream.rangeClosed(1,3).forEach(i -> {
            couponRepository.save(
                    Coupon.builder()
                            .name("coupon" + i)
                            .code("code" + i)
                            .type(CouponType.DISCOUNT)
                            .status(CouponStatus.PUBLIC)
                            .startDate(LocalDate.now())
                            .endDate(LocalDate.now().plusDays(7))
                            .build()
            );
        });
    }

}

2) CommandLineRunner

@Configuration
@Profile({"test", "dev"})    // test 환경에서만 실행
public class TestInitData {

    // CommandLineRunner : 애플리케이션 실행 시점에 특정 코드를 실행하고 싶을 때 사용

    @Bean
    CommandLineRunner init(RoleRepository roleRepository) {
        return (args) -> {
            Optional<Role> role = roleRepository.findByName("ROLE_USER");
            if (!role.isPresent()) {
                roleRepository.save(Role.builder().name("ROLE_USER").build());
            }
        };
    }
}

3) Schema.sql

설정
build.gradle

    // h2
    runtimeOnly 'com.h2database:h2'

application-test.yml

spring:
  sql:
    init:
      schema-locations: classpath:h2/schema.sql  # 테이블 생성 파일 경로 application.yml 파일이 있는 resources/h2/schema.sql 위치
			data-locations: classpath:h2/data.sql

☑️ 해당 경로 classpath를 상대경로 or 절대경로를 잘 인지하고 해주어야 한다!

  • schema.sql
DROP TABLE IF EXISTS coupon;

CREATE TABLE coupon
(
    id          bigint auto_increment primary key,
    code        VARCHAR(255) not null,
    end_date    DATE         null,
    name        VARCHAR(255) not null,
    start_date  DATE         null,
    status      VARCHAR(255) not null,
    type        VARCHAR(255) not null,
    created_at  TIMESTAMP    null,
    modified_at TIMESTAMP    null
);
  • data.sql
INSERT INTO coupon (code, end_date, name, start_date, status, type, created_at, modified_at) 
VALUES ('SAVE10', '2024-12-31', '10% Off', '2024-01-01', 'active', 'discount', '2024-01-01 00:00:00', '2024-01-01 00:00:00');

INSERT INTO coupon (code, end_date, name, start_date, status, type, created_at, modified_at) 
VALUES ('FREESHIP', null, 'Free Shipping', '2024-01-01', 'active', 'shipping', '2024-01-01 00:00:00', null);

INSERT INTO coupon (code, end_date, name, start_date, status, type, created_at, modified_at) 
VALUES ('WELCOME', '2024-06-30', 'Welcome Discount', '2024-01-01', 'expired', 'welcome', '2024-01-01 00:00:00', '2024-06-30 00:00:00');

INSERT INTO coupon (code, end_date, name, start_date, status, type, created_at, modified_at) 
VALUES ('HOLIDAY20', '2024-12-25', 'Holiday Sale', '2024-11-01', 'active', 'seasonal', '2024-11-01 00:00:00', '2024-11-01 00:00:00');

INSERT INTO coupon (code, end_date, name, start_date, status, type, created_at, modified_at) 
VALUES ('SUMMER', '2024-08-31', 'Summer Sale', '2024-06-01', 'expired', 'seasonal', '2024-06-01 00:00:00', '2024-08-31 00:00:00');

4) 🌟 data.sql

☑️ data.sql 만으로 진행할 수 있습니다. schema.sql 로, 또는 JPA ddl-auto로 이미 MySQL schema 는 만들어진 상태
😊 개인적으로 이 방법을 더 애용합니다!

data.sql


-- 기존 데이터 삭제
SET FOREIGN_KEY_CHECKS = 0;  -- 외래키 체크 비활성화

TRUNCATE TABLE `member`;
TRUNCATE TABLE `member_role_list`;
TRUNCATE TABLE `category`;
TRUNCATE TABLE `product`;
TRUNCATE TABLE `product_image_list`;
TRUNCATE TABLE `tag`;
TRUNCATE TABLE `product_tag`;


SET FOREIGN_KEY_CHECKS = 1;  -- 외래키 체크 다시 활성화


-- 데이터 입력
-- ...

❗ 주의사항

schema.sql 없이 data.sql만 넣는 방식! ddl-auto: create-drop 설정을 하고 sql init 을 실행하여야 한다.

sql 위치

application.yml

server:
  port: 8090

spring:
  
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/shop
    username: root
    password: 1234
#    hikari:
#      maximum-pool-size: 25 # 최대 connection 수
#      max-lifetime: 25000 # 25초, 커넥션이 풀에서 제거되기 전까지의 최대 수명(밀리초), DB wait_timeout(28.3초) 보다 짧게 설정

  jpa:
    hibernate:
      ddl-auto: create-drop # 테이블 생성 및 업데이트 전략 (create, create-drop, update, validate, none)
    defer-datasource-initialization: true # DataSource 초기화 지연
    properties:
      hibernate:
        dialect: org.hibernate.dialect.MySQL8Dialect # Hibernate Dialect 설정
        format_sql: true # SQL 포맷팅
        highlight_sql: true # SQL 하이라이트 출력
        use_sql_comments: true # JPQL SQL 주석 사용
        default_batch_fetch_size: 100 # 기본 배치 크기 설정
    
  sql:
    init:
      platform: mysql # SQL 초기화 플랫폼 (mysql, h2, postgresql, oracle, sqlserver)
      data-locations: classpath:sql/data.sql # ddl-auto가 create, create-drop, update일 때 데이터 초기화, 초기화 완료후 validate/none로 변경
      mode: always # SQL 초기화 모드 (always, never, embedded, embedded-always)    


logging:
  level:
    #    org.springframework.security.web: trace
    org.hibernate: info # Hibernate의 로그 레벨을 info로 설정
    org.hibernate.orm.jdbc.bind: trace # Hibernate의 SQL 바인딩을 출력
profile
배운 것을 기록합니다.

0개의 댓글

관련 채용 정보