1. 개요

Spring Boot를 사용하면 데이터베이스 변경 사항을 쉽게 관리 할 수 ​​있습니다. 기본 구성을 그대로두면 패키지에서 엔터티를 검색하고 각 테이블을 자동으로 생성합니다.

그러나 때때로 우리는 데이터베이스 변경에 대해 좀 더 세밀한 제어가 필요할 것입니다. 이때 Spring에서 data.sqlschema.sql 파일을 사용할 수 있습니다 .

2. data.sql 파일

또한 여기서 JPA로 작업하고 있다고 가정 하고 프로젝트에서 간단한 국가 엔터티를 정의 해 보겠습니다 .

@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은이 파일을 선택하여 스키마 생성에 사용합니다.

충돌을 피하기 위해 자동 스키마 생성을 해제하는 것도 중요합니다.

spring.jpa.hibernate.ddl-auto=none

4. Hibernate를 사용하여 데이터베이스 생성 제어

Spring은 Hibernate가 DDL 생성을 위해 사용 하는 JPA 특정 속성을 제공합니다 : spring.jpa.hibernate.ddl-auto .

표준 Hibernate 속성 값은 create , update , create-drop , validatenone입니다 .

  • create – Hibernate는 먼저 기존 테이블을 삭제 한 다음 새 테이블을 생성합니다.
  • update – 매핑 (어노테이션 또는 XML)을 기반으로 생성 된 객체 모델을 기존 스키마와 비교 한 다음 Hibernate가 diff에 따라 스키마를 업데이트합니다. 응용 프로그램에서 더 이상 필요하지 않더라도 기존 테이블 또는 열을 삭제하지 않습니다.
  • create-dropcreate 와 유사하며  모든 작업이 완료된 후 Hibernate가 데이터베이스를 삭제한다는 추가 사항이 있습니다. 일반적으로 단위 테스트에 사용
  • validate – Hibernate는 테이블과 열이 존재하는지 여부 만 확인합니다. 그렇지 않으면 예외가 발생합니다.
  • 없음 –이 값은 DDL 생성을 효과적으로 해제합니다.

Spring Boot  는 스키마 관리자가 감지되지 않은 경우 내부적으로이 매개 변수 값을 create-drop으로 기본 설정하고 , 그렇지 않은  경우 다른 모든 경우에는 없음기본값으로 설정합니다 .

값을 신중하게 설정하거나 다른 메커니즘 중 하나를 사용하여 데이터베이스를 초기화해야합니다.

5. @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());
}

6. @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 Bean의 이름
  • encoding – SQL 스크립트 파일의 인코딩, 기본값은 플랫폼 인코딩입니다.
  • errorMode – 스크립트 실행 중 오류가 발생했을 때 사용되는 모드
  • separator – 개별 명령문을 구분하는 데 사용되는 문자열, 기본값은 "–"입니다.
  • transactionManager트랜잭션에 사용될 PlatformTransactionManager  의 빈 이름
  • transactionMode트랜잭션 에서 스크립트를 실행할 때 사용되는 모드

7. @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());
   }
   }

8. 결론

이 빠른 기사에서는 초기 스키마를 설정하고 데이터로 채우기 위해 schema.sqldata.sql 파일을 활용 하는 방법을 살펴 보았습니다 . 또한 @Sql, @SqlConfig@SqlGroup 어노테이션을 사용하여 테스트 용 테스트 데이터를로드 하는 방법도 살펴 보았습니다 .

이 접근 방식은 기본적이고 간단한 시나리오에 더 적합하며, 모든 고급 데이터베이스 처리에는 Liquibase 또는 Flyway 와 같은보다 고급적이고 세련된 도구가 필요합니다 .

항상 그렇듯이 코드 조각 은 GitHub 에서 찾을 수 있습니다 .