嵌入式資料庫支援
建立嵌入式資料庫
您可以將嵌入式資料庫例項作為 bean 暴露,如下例所示
-
Java
-
Kotlin
-
Xml
@Bean
DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.generateUniqueName(true)
.setType(EmbeddedDatabaseType.H2)
.addScripts("schema.sql", "test-data.sql")
.build();
}
@Bean
fun dataSource() = EmbeddedDatabaseBuilder()
.generateUniqueName(true)
.setType(EmbeddedDatabaseType.H2)
.addScripts("schema.sql", "test-data.sql")
.build()
<jdbc:embedded-database id="dataSource" generate-name="true" type="H2">
<jdbc:script location="classpath:schema.sql"/>
<jdbc:script location="classpath:test-data.sql"/>
</jdbc:embedded-database>
上述配置建立了一個嵌入式 H2 資料庫,該資料庫從類路徑根目錄下的 schema.sql
和 test-data.sql
資源載入 SQL 進行填充。此外,作為最佳實踐,嵌入式資料庫被分配了一個唯一生成的名稱。該嵌入式資料庫作為型別為 javax.sql.DataSource
的 bean 提供給 Spring 容器,然後可以根據需要注入到資料訪問物件中。
有關所有支援選項的更多詳細資訊,請參閱 EmbeddedDatabaseBuilder
的 javadoc。
選擇嵌入式資料庫型別
本節介紹瞭如何選擇 Spring 支援的三種嵌入式資料庫之一。包括以下主題
使用 HSQL
Spring 支援 HSQL 1.8.0 及以上版本。如果未明確指定型別,HSQL 是預設的嵌入式資料庫。要顯式指定 HSQL,請將 embedded-database
標籤的 type
屬性設定為 HSQL
。如果使用 builder API,請呼叫 setType(EmbeddedDatabaseType)
方法並傳入 EmbeddedDatabaseType.HSQL
。
自定義嵌入式資料庫型別
雖然每種支援的型別都帶有預設連線設定,但如有必要可以自定義它們。以下示例使用帶有自定義驅動程式的 H2
-
Java
-
Kotlin
@Configuration
public class DataSourceConfig {
@Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setDatabaseConfigurer(EmbeddedDatabaseConfigurers
.customizeConfigurer(H2, this::customize))
.addScript("schema.sql")
.build();
}
private EmbeddedDatabaseConfigurer customize(EmbeddedDatabaseConfigurer defaultConfigurer) {
return new EmbeddedDatabaseConfigurerDelegate(defaultConfigurer) {
@Override
public void configureConnectionProperties(ConnectionProperties properties, String databaseName) {
super.configureConnectionProperties(properties, databaseName);
properties.setDriverClass(CustomDriver.class);
}
};
}
}
@Configuration
class DataSourceConfig {
@Bean
fun dataSource(): DataSource {
return EmbeddedDatabaseBuilder()
.setDatabaseConfigurer(EmbeddedDatabaseConfigurers
.customizeConfigurer(EmbeddedDatabaseType.H2) { this.customize(it) })
.addScript("schema.sql")
.build()
}
private fun customize(defaultConfigurer: EmbeddedDatabaseConfigurer): EmbeddedDatabaseConfigurer {
return object : EmbeddedDatabaseConfigurerDelegate(defaultConfigurer) {
override fun configureConnectionProperties(
properties: ConnectionProperties,
databaseName: String
) {
super.configureConnectionProperties(properties, databaseName)
properties.setDriverClass(CustomDriver::class.java)
}
}
}
}
使用嵌入式資料庫測試資料訪問邏輯
嵌入式資料庫提供了一種輕量級的方式來測試資料訪問程式碼。下一個示例是使用嵌入式資料庫的資料訪問整合測試模板。當嵌入式資料庫不需要在測試類之間重用時,使用此類模板對於一次性測試非常有用。但是,如果您希望建立在測試套件內共享的嵌入式資料庫,請考慮使用 Spring TestContext Framework 並按照 建立嵌入式資料庫 中所述,將嵌入式資料庫配置為 Spring ApplicationContext
中的 bean。以下列表顯示了測試模板
-
Java
-
Kotlin
public class DataAccessIntegrationTestTemplate {
private EmbeddedDatabase db;
@BeforeEach
public void setUp() {
// creates an HSQL in-memory database populated from default scripts
// classpath:schema.sql and 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() {
// creates an HSQL in-memory database populated from default scripts
// classpath:schema.sql and 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
配置僅在啟用的 bean 定義 profile 方面有所不同。
此類錯誤的根本原因在於 Spring 的 EmbeddedDatabaseFactory
(在 <jdbc:embedded-database>
XML 名稱空間元素和用於 Java 配置的 EmbeddedDatabaseBuilder
內部使用)在未另行指定的情況下,會將嵌入式資料庫的名稱設定為 testdb
。對於 <jdbc:embedded-database>
的情況,嵌入式資料庫通常被分配一個等於 bean 的 id
的名稱(通常是像 dataSource
這樣的名稱)。因此,後續嘗試建立嵌入式資料庫不會產生新的資料庫。相反,而是重用了相同的 JDBC 連線 URL,並且嘗試建立新嵌入式資料庫實際上指向了從相同配置建立的現有嵌入式資料庫。
為了解決這個常見問題,Spring Framework 4.2 提供了為嵌入式資料庫生成唯一名稱的支援。要啟用生成名稱的使用,請使用以下選項之一。
-
EmbeddedDatabaseFactory.setGenerateUniqueDatabaseName()
-
EmbeddedDatabaseBuilder.generateUniqueName()
-
<jdbc:embedded-database generate-name="true" … >
擴充套件嵌入式資料庫支援
您可以透過兩種方式擴充套件 Spring JDBC 嵌入式資料庫支援
-
實現
EmbeddedDatabaseConfigurer
以支援新的嵌入式資料庫型別。 -
實現
DataSourceFactory
以支援新的DataSource
實現,例如用於管理嵌入式資料庫連線的連線池。
我們鼓勵您透過 GitHub Issues 向 Spring 社群貢獻擴充套件。