Пакет org.springframework.jdbc.datasource.embedded забезпечує підтримку вбудованих підсистем зберігання на Java. Підтримка HSQL, H2 та Derby забезпечується нативно. Також можна використовувати розширюваний API-інтерфейс для підключення нових вбудованих типів баз даних та реалізацій DataSource.

Навіщо використовувати вбудовану базу даних?

Вбудована база даних може бути корисна на етапі розробки проекту завдяки своїй спрощеності. Серед переваг простота налаштування, швидкий час запуску, тестованість і можливість швидкого доопрацювання SQL у процесі розробки. як бін у 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-інтерфейс для створення вбудованої бази даних програмним шляхом. Це можна використовувати, якщо потрібно створити вбудовану базу даних в автономному оточенні або в автономному інтеграційному тесті, як у наступному прикладі:

Java
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()
Kotlin
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 , як показано в наступному прикладі:

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(); } }
Kotlin
@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, як це описано вище. У наступному лістингу показаний тестовий шаблон:

Java
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(); } }
Kotlin
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 встановлює ім'я вбудованої бази даних на 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.