嵌入式資料庫支援
建立嵌入式資料庫
你可以將嵌入式資料庫例項作為 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。如果使用構建器 API,請使用 EmbeddedDatabaseType.HSQL 呼叫 setType(EmbeddedDatabaseType) 方法。
自定義嵌入式資料庫型別
雖然每種支援的型別都帶有預設連線設定,但如有必要,也可以自定義它們。以下示例使用帶有自定義驅動程式的 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 框架,並按照 建立嵌入式資料庫 中所述,將嵌入式資料庫配置為 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 定義配置檔案方面有所不同。
此類錯誤的根本原因是,如果未另行指定,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 社群貢獻擴充套件。