Пакет org.springframework.jdbc.datasource.embedded
обеспечивает поддержку встроенных подсистем хранения на Java. Поддержка HSQL, H2 и Derby обеспечивается нативно. Также можно использовать расширяемый API-интерфейс для подключения новых встроенных типов баз данных и реализаций DataSource
.
Зачем использовать встроенную базу данных?
Встроенная база данных может быть полезна на этапе разработки проекта благодаря своей упрощенности. Среди преимуществ простота настройки, быстрое время запуска, тестируемость и возможность быстрой доработки SQL в процессе разработки.
Создание встроенной базы данных с помощью Spring XML
Если вам нужно представить экземпляр встроенной базы данных в качестве бина в ApplicationContext
в Spring, можно использовать тег embedded-database
в пространстве имен spring-jdbc
:
<jdbc:embedded-database id="dataSource" generate-name="true">
<jdbc:script location="classpath:schema.sql"/>
<jdbc:script location="classpath:test-data.sql"/>
</jdbc:embedded-database>
Предыдущая конфигурация создает встроенную базу данных HSQL, которая заполняется SQL из ресурсов schema.sql
и test-data.sql
в корне classpath. Кроме того, в качестве оптимального метода работы встроенной базе данных присваивается уникальное имя. Встроенная база данных становится доступной для контейнера Spring как бин типа javax.sql.DataSource
, который затем можно внедрять в объекты доступа к данным по мере необходимости.
Создание встроенной базы данных программным способом
Класс EmbeddedDatabaseBuilder
предоставляет свободный API-интерфейс для создания встроенной базы данных программным путем. Это можно использовать, если нужно создать встроенную базу данных в автономном окружении или в автономном интеграционном тесте, как в следующем примере:
EmbeddedDatabase db = new EmbeddedDatabaseBuilder()
.generateUniqueName(true)
.setType(H2)
.setScriptEncoding("UTF-8")
.ignoreFailedDrops(true)
.addScript("schema.sql")
.addScripts("user_data.sql", "country_data.sql")
.build();
// выполняем действия с базой данных (EmbeddedDatabase расширяет javax.sql.DataSource)
db.shutdown()
val db = EmbeddedDatabaseBuilder()
.generateUniqueName(true)
.setType(H2)
.setScriptEncoding("UTF-8")
.ignoreFailedDrops(true)
.addScript("schema.sql")
.addScripts("user_data.sql", "country_data.sql")
.build()
// выполняем действия с базой данных (EmbeddedDatabase расширяет javax.sql.DataSource)
db.shutdown()
См. javadoc по EmbeddedDatabaseBuilder
для получения более подробной информации обо всех поддерживаемых опциях.
Также можно использовать EmbeddedDatabaseBuilder
для создания встроенной базы данных с помощью конфигурации Java, как показано в следующем примере:
@Configuration
public class DataSourceConfig {
@Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.generateUniqueName(true)
.setType(H2)
.setScriptEncoding("UTF-8")
.ignoreFailedDrops(true)
.addScript("schema.sql")
.addScripts("user_data.sql", "country_data.sql")
.build();
}
}
@Configuration
class DataSourceConfig {
@Bean
fun dataSource(): DataSource {
return EmbeddedDatabaseBuilder()
.generateUniqueName(true)
.setType(H2)
.setScriptEncoding("UTF-8")
.ignoreFailedDrops(true)
.addScript("schema.sql")
.addScripts("user_data.sql", "country_data.sql")
.build()
}
}
Выбор типа встроенной базы данных
В этом разделе рассказывается о том, как выбрать одну из трех встроенных баз данных, которые поддерживает Spring. Раздел включает в себя следующие темы:
-
Использование HSQL
-
Использование H2
-
Использование Derby
Использование HSQL
Spring поддерживает HSQL 1.8.0 и выше. HSQL является встроенной базой данных по умолчанию, если тип не задан явным образом. Чтобы явно задать HSQL, установите для атрибута type
тега embedded-database
значение HSQL
. Если вы используете API-интерфейс сресдтва сборки, вызовите метод setType(EmbeddedDatabaseType)
с параметром EmbeddedDatabaseType.HSQL
.
Использование H2
Spring поддерживает базу данных H2. Чтобы активировать H2, установите для атрибута type
тега embedded-database
значение H2
. Если вы используете API-интерфейс средства сборки, вызовите метод setType(EmbeddedDatabaseType)
с параметром EmbeddedDatabaseType.H2
.
Использование Derby
Spring поддерживает Apache Derby 10.5 и выше. Чтобы активировать Derby, установите для атрибута type
тега embedded-database
значение DERBY
. Если вы используете API-интерфейс средства сборки, вызовите метод setType(EmbeddedDatabaseType)
с параметром EmbeddedDatabaseType.DERBY
.
Тестирование логики доступа к данным с использованием встроенной базы данных
Встроенные базы данных обеспечивают легкий способ тестирования кода для получения выборки данных. Следующий пример - шаблон интеграционного теста доступа к данным, в котором используется встроенная база данных. Использование такого шаблона может быть полезно для разовых случаев, если встроенную базу данных не нужно использовать повторно во всех тестовых классах. Однако если нужно создать встроенную базу данных, которая будет использоваться совместно в тестовом комплекте, используйте Spring TestContext Framework и сконфигурируйте встроенную базу данных как бин в ApplicationContext
из Spring, как это описано выше. В следующем листинге показан тестовый шаблон:
public class DataAccessIntegrationTestTemplate {
private EmbeddedDatabase db;
@BeforeEach
public void setUp() {
// создает резидентную (с хранением в оперативной памяти) базу данных HSQL, заполненную скриптами по умолчанию
// classpath:schema.sql и classpath:data.sql
db = new EmbeddedDatabaseBuilder()
.generateUniqueName(true)
.addDefaultScripts()
.build();
}
@Test
public void testDataAccess() {
JdbcTemplate template = new JdbcTemplate(db);
template.query( /* ... */ );
}
@AfterEach
public void tearDown() {
db.shutdown();
}
}
class DataAccessIntegrationTestTemplate {
private lateinit var db: EmbeddedDatabase
@BeforeEach
fun setUp() {
// создает резидентную (с хранением в оперативной памяти) базу данных HSQL, заполненную скриптами по умолчанию
// classpath:schema.sql и classpath:data.sql
db = EmbeddedDatabaseBuilder()
.generateUniqueName(true)
.addDefaultScripts()
.build()
}
@Test
fun testDataAccess() {
val template = JdbcTemplate(db)
template.query( /* ... */)
}
@AfterEach
fun tearDown() {
db.shutdown()
}
}
Создание уникальных имен для встроенных баз данных
Команды разработчиков часто сталкиваются с ошибками при работе со встроенными базами данных, если их тестовый комплект случайно пытается воссоздать дополнительные экземпляры одной и той же базы данных. Это довольно легко может произойти, если файл конфигурации XML или класс с аннотацией @Configuration
отвечает за создание встроенной базы данных, а соответствующая конфигурация затем повторно используется в нескольких сценариях тестирования в рамках одного тестового комплекта (то есть в рамках одного процесса JVM) – например, интеграционные тесты в отношении встроенных баз данных, конфигурация ApplicationContext
которых отличается только тем, какие профили определения бинов активны.
Первопричиной таких ошибок является тот факт, что фабрика EmbeddedDatabaseFactory
из Spring (используемая внутренним способом как элементом пространства имен XML <jdbc:embedded-database>
, так и конфигурацией EmbeddedDatabaseBuilder
для Java) устанавливает имя встроенной базы данных на testdb
, если не задано иное. В случае <jdbc:embedded-database>
, встроенной базе данных обычно присваивается имя, равное id
бина (зачастую наподобие dataSource
). Таким образом, последующие попытки создать встроенную базу данных не приводят к созданию новой базы данных. Вместо этого повторно используется один и тот же URL-адрес подключения JDBC, а попытки создать новую встроенную базу данных фактически указывают на существующую встроенную базу данных, созданную на основе той же конфигурации.
Для решения этой распространенной проблемы в Spring Framework 4.2 предусмотрены средства поддержки генерации уникальных имен для встроенных баз данных. Чтобы активировать функцию использования сгенерированных имен, используйте один из следующих параметров.
-
EmbeddedDatabaseFactory.setGenerateUniqueDatabaseName()
-
EmbeddedDatabaseBuilder.generateUniqueName()
-
<jdbc:embedded-database generate-name="true" … >
Расширение поддержки встроенных баз данных
Можно расширить средства поддержки встроенных баз данных JDBC в Spring двумя способами:
-
Путем реализации
EmbeddedDatabaseConfigurer
для обеспечения поддержки нового типа встроенной базы данных. -
Путем реализации
DataSourceFactory
для обеспечения поддержки новой реализацииDataSource
, например, пула соединений, чтобы управлять подключениями к встроенной базе данных.
Мы призываем вас вносить свои предложения касательно расширений в сообществе Spring на GitHub Issues.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ