Краткое руководство по загрузке исходных данных с помощью Spring Boot
1. обзор
Spring Boot позволяет легко и просто управлять изменениями в нашей базе данных. Если мы оставим конфигурацию по умолчанию, он будет искать объекты в наших пакетах и автоматически создавать соответствующие таблицы.
Но иногда нам может потребоваться более тонкий контроль над изменениями базы данных. Вот тогда мы можем использовать файлыdata.sql иschema.sql в Spring.
2. Файлdata.sql
Давайте также сделаем предположение, что мы работаем с JPA, и определим простую сущностьCountry в нашем проекте:
@Entity
public class Country {
@Id
@GeneratedValue(strategy = IDENTITY)
private Integer id;
@Column(nullable = false)
private String name;
//...
}
Если мы запустим наше приложение,Spring Boot will create an empty table for us, but won’t populate it with anything.
Легкий способ сделать это - создать файл с именем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');
Когда мы запустим проект с этим файлом в classpath, 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. Управление созданием базы данных с помощью гибернации
Spring предоставляет специфичный для JPAproperty which Hibernate uses for DDL generation:*spring.jpa.hibernate.ddl-auto*.
Стандартные значения свойств Hibernate:create,update,create-drop,validate иnone:
-
create - Hibernate сначала удаляет существующие таблицы, а затем создает новые таблицы
-
update - объектная модель, созданная на основе сопоставлений (аннотаций или XML), сравнивается с существующей схемой, а затем Hibernate обновляет схему в соответствии с diff. Он никогда не удаляет существующие таблицы или столбцы, даже если они больше не требуются приложению
-
create-drop - аналогcreate, с той лишь разницей, что Hibernate удалит базу данных после завершения всех операций. Обычно используется для модульного тестирования
-
validate - Hibernate только проверяет, существуют ли таблицы и столбцы, иначе выдает исключение.
-
none - это значение эффективно отключает генерацию DDL
Spring Boot внутренне устанавливает значение этого параметра по умолчанию наcreate-drop, если диспетчер схемы не был обнаружен, в противном случаеnone для всех остальных случаев.
Нам нужно тщательно установить значение или использовать один из других механизмов для инициализации базы данных.
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
-
statements – we может объявлять встроенные операторы SQL для выполнения
-
scripts – we может объявлять пути к файлам сценариев SQL для выполнения. Это псевдоним атрибутаvalue
Аннотация@Sqlcan be used at the class level or the method level. Мы можем загрузить дополнительные данные, необходимые для конкретного тестового примера, пометив этот метод:
@Test
@Sql({"/import_senior_employees.sql"})
public void testLoadDataForTestCase() {
assertEquals(5, employeeRepository.findAll().size());
}
6. @SqlConfigс
Мы можемconfigure the way we parse and run the SQL scripts, используя аннотацию@SqlConfig.
@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 - имя bean-компонентаjavax.sql.DataSource, для которого будут запускаться скрипты и операторы
-
encoding - кодировка для файлов сценария SQL, по умолчанию кодировка платформы
-
errorMode - режим, который будет использоваться при обнаружении ошибки при запуске скриптов
-
separator - строка, используемая для разделения отдельных операторов, по умолчанию «-»
-
transactionManager - имя bean-компонентаPlatformTransactionManager , который будет использоваться для транзакций
-
transactionMode - режим, который будет использоваться при выполнении скриптов в транзакции
7. @SqlGroupс
Java 8 и выше позволяют использовать повторные аннотации. Эту функцию также можно использовать для аннотаций@Sql. Для Java 7 и ниже существует аннотация контейнера -@SqlGroup. Using the @SqlGroup annotation, we can declare multiple @Sql annotations:
@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.sql иdata.sql для настройки начальной схемы и заполнения ее данными. Мы также увидели, как мы можем использовать аннотации@Sql, @SqlConfig и@SqlGroup для загрузки тестовых данных для тестов.
Имейте в виду, что этот подход больше подходит для базовых и простых сценариев, любая расширенная обработка базы данных потребует более сложных и усовершенствованных инструментов, таких какLiquibase илиFlyway.
Фрагменты кода, как всегда, можно найтиover on GitHub.