https://www.baeldung.com/spring-boot-data-sql-and-schema-sql/를 번역함.
1. 개요
Spring Boot를 사용하면 데이터베이스 변경 사항을 정말 쉽게 관리할 수 있습니다. 기본 구성을 그대로 두면 패키지에서 엔터티를 검색하고 해당 테이블을 자동으로 생성합니다.
그러나 때때로 데이터베이스 변경에 대해 보다 세분화된 제어가 필요합니다. 그리고 그 때 우리는 Spring에서 data.sql 및 schema.sql 파일을 사용할 수 있습니다 .
2. data.sql 파일
또한 여기에서 JPA로 작업 하고 프로젝트에서 간단한 Country 엔터티를 정의한다고 가정하겠습니다 .
@Entity
public class Country {
@Id
@GeneratedValue(strategy = IDENTITY)
private Integer id;
@Column(nullable = false)
private String name;
//...
}
우리가 애플리케이션을 실행하면 Spring Boot는 우리를 위해 빈 테이블을 생성하지만 아무 것도 채우지 않을 것입니다.
이를 수행하는 쉬운 방법은 data.sql 이라는 파일을 만드는 것입니다 .
INSERT INTO country (name) VALUES ('India');
INSERT INTO country (name) VALUES ('Brazil');
INSERT INTO country (name) VALUES ('USA');
INSERT INTO country (name) VALUES ('Italy');
클래스 경로에서 이 파일로 프로젝트를 실행하면 Spring이 이를 선택하여 데이터베이스를 채우는 데 사용합니다.
3. schema.sql 파일
때로는 기본 스키마 생성 메커니즘에 의존하고 싶지 않습니다.
이러한 경우 사용자 지정 schema.sql 파일을 생성할 수 있습니다 .
CREATE TABLE country (
id INTEGER NOT NULL AUTO_INCREMENT,
name VARCHAR(128) NOT NULL,
PRIMARY KEY (id)
);
Spring은 이 파일을 선택하여 스키마 생성에 사용할 것입니다.
schema.sql 및 data.sql을 통한 스크립트 기반 초기화 와 Hibernate 초기화를 함께 사용하면 몇 가지 문제가 발생할 수 있습니다.
Hibernate 자동 스키마 생성을 비활성화하거나:
spring.jpa.hibernate.ddl-auto=none
이렇게 하면 schema.sql 및 data.sql을 직접 사용하여 스크립트 기반 초기화가 수행 됩니다.
스크립트 기반 스키마 생성 및 데이터 채우기와 결합하여 Hibernate 자동 스키마 생성을 모두 사용하려면 다음을 사용해야 합니다.
spring.jpa.defer-datasource-initialization=true
이것은 Hibernate 스키마 생성이 수행된 후 추가 스키마 변경에 대해 추가로 schema.sql 을 읽고 data.sql 을 실행하여 데이터베이스를 채우는 것을 보장 합니다.
또한 스크립트 기반 초기화는 기본적으로 포함된 데이터베이스에 대해서만 수행되며 항상 스크립트를 사용하여 데이터베이스를 초기화하려면 다음을 사용해야 합니다.
spring.sql.init.mode=always
SQL 스크립트를 사용한 데이터베이스 초기화 에 대한 공식 Spring 문서를 참조하십시오 .
4. Hibernate를 사용하여 데이터베이스 생성 제어
Spring은 Hibernate가 DDL 생성을 위해 사용 하는 JPA 특정 속성인 spring.jpa.hibernate.ddl-auto를 제공한다 .
표준 Hibernate 속성 값은 create , update , create-drop , validate 및 none 입니다 .
- create – Hibernate는 먼저 기존 테이블을 삭제한 다음 새 테이블을 생성합니다.
- update - 매핑(주석 또는 XML)을 기반으로 생성된 객체 모델을 기존 스키마와 비교한 다음 Hibernate가 diff에 따라 스키마를 업데이트합니다. 애플리케이션에서 더 이상 필요하지 않은 경우에도 기존 테이블이나 열을 삭제하지 않습니다.
- create-drop – 모든 작업이 완료된 후 Hibernate가 데이터베이스를 삭제할 것이라는 추가와 함께 create 와 유사합니다 . 일반적으로 단위 테스트에 사용
- validate – Hibernate는 테이블과 열이 존재하는지 여부만 검증합니다. 그렇지 않으면 예외가 발생합니다.
- 없음 – 이 값은 DDL 생성을 효과적으로 끕니다.
Spring Boot는 내부적으로 스키마 관리자가 감지되지 않은 경우 이 매개변수 값을 create-drop으로 기본 설정하고 , 그렇지 않으면 다른 모든 경우에는 없음 을 설정합니다.
값을 신중하게 설정하거나 다른 메커니즘 중 하나를 사용하여 데이터베이스를 초기화해야 합니다.
5. 데이터베이스 스키마 생성 사용자 정의
기본적으로 Spring Boot는 내장된 DataSource 의 스키마를 자동으로 생성합니다 .
이 동작을 제어하거나 사용자 정의해야 하는 경우 spring.sql.init.mode 속성을 사용할 수 있습니다 . 이 속성은 다음 세 가지 값 중 하나를 사용합니다.
- 항상 – 항상 데이터베이스를 초기화합니다.
- 내장 – 내장 데이터베이스가 사용 중인 경우 항상 초기화합니다. 속성 값이 지정되지 않은 경우 기본값입니다.
- Never – 데이터베이스를 초기화하지 않음
특히 MySQL이나 PostGreSQL과 같이 내장되지 않은 데이터베이스를 사용하고 스키마를 초기화하려면 이 속성을 always 로 설정해야 합니다 .
이 속성은 Spring Boot 2.5.0에서 도입되었습니다. 이전 버전의 Spring Boot 를 사용하는 경우 spring.datasource.initialization-mode 를 사용해야 합니다.
6. @SQL
Spring은 또한 테스트 스키마를 초기화하고 채우는 선언적 방법인 @Sql 주석을 제공합니다 .
@Sql 주석을 사용하여 새 테이블을 만들고 통합 테스트를 위해 초기 데이터가 있는 테이블을 로드하는 방법을 살펴보겠습니다 .
@Sql({"/employees_schema.sql", "/import_employees.sql"})
public class SpringBootInitialLoadIntegrationTest {
@Autowired
private EmployeeRepository employeeRepository;
@Test
public void testLoadDataForTestClass() {
assertEquals(3, employeeRepository.findAll().size());
}
}
@Sql 주석 의 속성은 다음과 같습니다 .
- config – SQL 스크립트에 대한 로컬 구성입니다. 다음 섹션에서 이에 대해 자세히 설명합니다.
- executionPhase – BEFORE_TEST_METHOD 또는 AFTER_TEST_METHOD 중 스크립트를 실행할 시기를 지정할 수도 있습니다 .
- 문 – 실행할 인라인 SQL 문을 선언할 수 있습니다.
- 스크립트 – 실행할 SQL 스크립트 파일의 경로를 선언할 수 있습니다. 이것은 값 속성 의 별칭입니다 .
@Sql의 주석은 클래스 레벨 또는 메소드 레벨에서 사용할 수 있습니다.
해당 메소드에 주석을 달아 특정 테스트 케이스에 필요한 추가 데이터를 로드합니다.
@Test
@Sql({"/import_senior_employees.sql"})
public void testLoadDataForTestCase() {
assertEquals(5, employeeRepository.findAll().size());
}
7. @SqlConfig
@SqlConfig 주석 을 사용하여 SQL 스크립트 를 구문 분석하고 실행하는 방식을 구성 할 수 있습니다 .
@SqlConfig 는 전역 구성으로 사용되는 클래스 수준에서 선언할 수 있습니다. 또는 특정 @Sql 주석 을 구성하는 데 사용할 수 있습니다 .
SQL 스크립트의 인코딩과 스크립트 실행을 위한 트랜잭션 모드를 지정하는 예를 살펴보겠습니다.
@Test
@Sql(scripts = {"/import_senior_employees.sql"},
config = @SqlConfig(encoding = "utf-8", transactionMode = TransactionMode.ISOLATED))
public void testLoadDataForTestCase() {
assertEquals(5, employeeRepository.findAll().size());
}
@SqlConfig 의 다양한 속성을 살펴보겠습니다 .
- blockCommentStartDelimiter – SQL 스크립트 파일에서 블록 주석의 시작을 식별하는 구분 기호
- blockCommentEndDelimiter – SQL 스크립트 파일에서 블록 주석의 끝을 나타내는 구분 기호
- commentPrefix – SQL 스크립트 파일에서 한 줄 주석을 식별하기 위한 접두사
- dataSource – 스크립트와 문이 실행될 javax.sql.DataSource 빈의 이름
- 인코딩 – SQL 스크립트 파일에 대한 인코딩 기본값은 플랫폼 인코딩입니다.
- errorMode – 스크립트 실행 중 오류가 발생했을 때 사용되는 모드
- 구분자 – 개별 명령문을 구분하는 데 사용되는 문자열. 기본값은 "-"입니다.
- transactionManager – 트랜잭션에 사용될 PlatformTransactionManager 의 빈 이름
- transactionMode – 트랜잭션 에서 스크립트를 실행할 때 사용할 모드
8. @SqlGroup
Java 8 이상에서는 반복되는 주석을 사용할 수 있습니다. @Sql 주석에도 이 기능을 활용할 수 있습니다. Java 7 이하의 경우 @SqlGroup 이라는 컨테이너 주석이 있습니다.
@SqlGroup 주석을 사용하여 여러 @Sql 주석을 선언합니다 .
@SqlGroup({
@Sql(scripts = "/employees_schema.sql",
config = @SqlConfig(transactionMode = TransactionMode.ISOLATED)),
@Sql("/import_employees.sql")})
public class SpringBootSqlGroupAnnotationIntegrationTest {
@Autowired
private EmployeeRepository employeeRepository;
@Test
public void testLoadDataForTestCase() {
assertEquals(3, employeeRepository.findAll().size());
}
}
9. 결론
이 빠른 기사에서는 초기 스키마를 설정하고 데이터로 채우는 데 schema.sql 및 data.sql 파일을 활용 하는 방법을 살펴보았습니다 .
또한 @Sql , @SqlConfig 및 @SqlGroup 주석을 사용하여 테스트용 테스트 데이터를 로드 하는 방법도 살펴보았습니다 .
이 접근 방식은 기본 및 간단한 시나리오에 더 적합하며 고급 데이터베이스 처리에는 Liquibase 또는 Flyway 와 같은 고급 및 세련된 도구가 필요합니다 .
코드 스니펫은 언제나처럼 GitHub 에서 찾을 수 있습니다 .