|
对于最新的稳定版本,请使用 Spring Framework 7.0.6! |
嵌入式数据库支持
使用Spring XML创建嵌入式数据库
如果您希望将嵌入式数据库实例作为Spring中的bean公开,
ApplicationContext,可以使用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数据库,并从类路径根目录中的schema.sql和test-data.sql资源中填充SQL。此外,作为最佳实践,嵌入式数据库被赋予了一个唯一生成的名称。嵌入式数据库作为类型为javax.sql.DataSource的bean提供给Spring容器,然后可以根据需要注入到数据访问对象中。
以编程方式创建嵌入式数据库
EmbeddedDatabaseBuilder 类提供了一个用于以编程方式构建嵌入式数据库的流畅 API。当您需要在独立环境或独立集成测试中创建嵌入式数据库时,可以使用此功能,如下例所示:
-
Java
-
Kotlin
EmbeddedDatabase db = new EmbeddedDatabaseBuilder()
.generateUniqueName(true)
.setType(H2)
.setScriptEncoding("UTF-8")
.ignoreFailedDrops(true)
.addScript("schema.sql")
.addScripts("user_data.sql", "country_data.sql")
.build();
// perform actions against the db (EmbeddedDatabase extends 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()
// perform actions against the db (EmbeddedDatabase extends javax.sql.DataSource)
db.shutdown()
查看 javadoc for EmbeddedDatabaseBuilder
以获取所有支持选项的更多详细信息。
您也可以使用 EmbeddedDatabaseBuilder 通过使用Java配置创建嵌入式数据库,如下例所示:
-
Java
-
Kotlin
@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
Spring 支持 HSQL 1.8.0 及以上版本。如果未明确指定类型,HSQL 是默认的嵌入式数据库。要显式指定 HSQL,请将 type 标签的 embedded-database 属性设置为 HSQL。如果您使用构建器 API,请使用 setType(EmbeddedDatabaseType) 方法并传入 EmbeddedDatabaseType.HSQL。
使用嵌入式数据库测试数据访问逻辑
嵌入式数据库为测试数据访问代码提供了一种轻量级的方法。下一个示例是一个使用嵌入式数据库的数据访问集成测试模板。在不需要跨测试类重用嵌入式数据库的情况下,使用这样的模板对于一次性任务可能很有用。然而,如果您希望在测试套件内创建一个共享的嵌入式数据库,请考虑使用Spring TestContext Framework并按照使用Spring XML创建嵌入式数据库和以编程方式创建嵌入式数据库中所述,在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 命名空间元素和 EmbeddedDatabaseBuilder Java 配置共同内部使用)如果未另外指定,会将嵌入式数据库的名称设置为 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社区贡献扩展。