처음 SpringBoot 어플리메이션을 실행시, DB 데이터를 미리 insert 하는 작업을 할시,
SpringBoot에서 할 수 있는 대표적인 3가지를 소개합니다.
개인적으로, @PostConstruct
를 더 추천합니다!
🌟 2) CommandLineRunner 를 주로 사용
@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()
);
});
}
}
@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());
}
};
}
}
설정
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 절대경로를 잘 인지하고 해주어야 한다!
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
);
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');
☑️ data.sql 만으로 진행할 수 있습니다. schema.sql 로 이미 MySQL schema 는 만들어진 상태
application.yml
server:
port: 8090
spring:
sql:
init:
platform: mysql
data-locations: classpath:sql/data.sql
mode: always # always, never, embedded, 처음 db init 시에만 always로 설정, jpa ddl-auto: create도 설정, 그 이후에는 never로 설정
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:
open-in-view: false
hibernate:
ddl-auto: create # 테이블 생성 및 업데이트 전략 (create, create-drop, update, validate, none)
show-sql: true # 실행되는 SQL을 콘솔에 출력
properties:
hibernate:
format_sql: true # SQL 포맷팅
dialect: org.hibernate.dialect.MySQL8Dialect # Hibernate가 사용할 방언, MySQL 8.0 성능 최적화를 위해 필요
defer-datasource-initialization: true # DataSource를 초기화하는 시점을 애플리케이션 구동 시점으로 지연시킴
logging:
level:
# org.springframework.security.web: trace
org.hibernate: info # Hibernate의 로그 레벨을 info로 설정
org.hibernate.orm.jdbc.bind: trace # Hibernate의 SQL 바인딩을 출력