스프링에서 test 패키지 내부에 data.sql을 넣은 것만으로도 data.sql 내부의 쿼리를 실행시킬 수 있다. 이런 방법으로 테스트용 더미 데이터를 생성하고 테스트를 동작시킬 수 있다. 비슷한 방법으로 DDL 동작이 필요한 경우에는 schema.sql을 만들어 내부에 create 등을 넣어두기만 하면 된다.
그런데 만약 schema.sql은 잘 동작하는데, data.sql이 제대로 동작하지 않는다면? 테스트에서 테이블이 생성되었지만 원하는 데이터가 나오지 않아 에러를 출력하는 경우가 있다. data.sql은 파일을 추가만 하면 되는 것이어서 별도의 세팅이 없기에 더욱 원인을 찾기 힘들다.
스프링 버전 및 sql.init.mode 이슈
내 경우에는 크게 두가지 원인이 있었다. 하나는 스프링 버전. 아래의 버전에서는 분명 문제없이 동작을 했다.
plugins {
id("org.springframework.boot") version "2.5.0"
(아래 생략)
이 2.5.x 버전에서 나타나는 이슈로 정확한 버전이 어딘지는 알 수 없지만 후반 버전에서는 쿼리, 그것도 insert, delete 등의 트랜잭션 이슈를 의심하게 할 쿼리가 제대로 동작하지 않는다. 이 경우에 sql 스크립트(여기서는 data.sql, schema.sql)을 어떻게 동작시킬지 세팅하는 init 설정이 필요하다. 아래에 v2.5.x라고 한 이유는 이 설정이 2.5.0에서는 제대로 동작을 하지 않았기 때문. 이 부분에 정확한 버전 시점을 아는 분이 있다면 댓글로 남겨주시길.
- v2.5.x 이상 설정: spring.sql.init.mode
- 위 버전 이하 설정 : spring.datasource.initialization-mode
// build.gradle.kts
plugins {
id("org.springframework.boot") version "2.5.13"
// application.yml
spring:
sql:
init:
mode: always
mode의 경우, 아래와 같은 옵션이 있다. 기본설정은 EMBDDED이다.
- ALWAYS: 모든 데이터베이스에 sql 스크립트를 동작시킨다.
- EMBDDED: embedded 데이터베이스만 sql 스크립트를 동작시킨다.
- NEVER: 모든 데이터베이스에 sql 스크립트를 동작시키지 않는다.
auto-commit: false
만약 스프링부트 2.5.0 이하 버전을 사용할 경우에는 auto-commit 이슈가 발목을 잡을 수 있다. 아래와 같이 auto-commit을 허용하지 않는다면 데이터가 생성되지 않는다. 개별 쿼리가 동작하면서 커밋이 되면서 데이터가 생성되어야 하는데 이를 막았기 때문.
// 데이터가 생성되지 않음
auto-commit: false
이게 테스트에만 세팅이 되어 있다면 문제가 아닐 수 있지만 실제 동작해야하는 코드쪽에 세팅이 되어 있다면 한번의 connection에 단일 트랜잭션 단위로 커밋을 할 수 있다. 이로인해 트랜잭션 단위로 롤백이 가능하다. 그래서 auto-commit을 허용하지 않는 경우가 많은데 이렇게 세팅하고 싶다면 첫번째에 제시한 방법처럼 스프링부트 버전을 올리고 mode를 추가해야 한다.
defer-datasource-initialization
이것도 스프링부트 버전과 관련있다. Hibernate 초기화 이전에 sql 스크립트를 실행할지를 설정할 수 있다. 그것이 바로 spring.jpa.defer-datasource-initialization 옵션이다. 아래와 같이 true로 세팅하면 하이버네이트 초기화 전에 쿼리가 실행되면서 데이터를 생성할 수 있다.
spring:
jpa:
defer-datasource-initialization: true
아무쪼록 해결 잘 하시고, 나같이 X고생을 안하길 바란다. 흑흑
참고자료
- 스프링부트 v2.5 - sql 스크립트 동작 설정방법 변경
- 스프링 부트 2.5 업데이트 : hibernate, data.sql 관련 변동사항
- 스프링부트 공식문서 - 86. Database Initialization
'Spring' 카테고리의 다른 글
스프링부트에서 쿠키(Cookie)를 구워보자 (0) | 2022.07.28 |
---|---|
Mockito가서 몰디브 한 잔, 긔? (with Kotlin) (0) | 2022.07.20 |
Google Oauth - Token 획득하기 (Signup/Signin용) (0) | 2022.03.30 |
코틀린 환경에서 Async 어노테이션 테스트하기 (0) | 2022.02.08 |
Kotlin에서 RestTemplateClient를 만들어보자 (0) | 2021.12.23 |
Comment