我正在开发一个新的Spring批处理(3.0.3.RELEASE)应用程序,在这个应用程序中可以访问多个数据库。为了进行测试,我们使用HSQLDB (2.3.2)作为嵌入式数据库。
在我的应用程序上下文中,我有以下内容。
<jdbc:embedded-database id="dataSource">
</jdbc:embedded-database>
<jdbc:embedded-database id="proDataSource">
<jdbc:script location="classpath:script-tables.sql" />
<jdbc:script location="classpath:script-constraints.sql" />
</jdbc:embedded-database>
<jdbc:embedded-database id="altDataSource">
<jdbc:script location="classpath:script-alt-tables.sql" />
</jdbc:embedded-database>当我在Eclipse中运行一个测试时,一切都很好。当我从命令行构建时,在第一个测试之后,我会得到错误。
Failed to execute SQL script statement at line 3 of resource class path resource [script-promrkt-promo.sql]
object name already exists: PROMRKT在我看来,EmbeddedDatabaseFactory中的人口进程正在接收一个已经填充的数据库。据我所知,每次测试之后,都不会执行关机,而且HSQLDB会将已经填充的数据库留在内存中。
我已经重新审查了文档,在弹簧医生中,这确实显示了一个显式的关机命令。但是,如果spring在我的测试开始时启动了嵌入式数据库,为什么它不在测试完成时关闭它呢?
发布于 2015-01-27 15:26:40
日志消息所抱怨的脚本不在您的配置中。我猜它是在别的地方被处决的吧?如果是这样的话,您可能需要将@DirtiesContext添加到您的测试中,这样Spring就不会缓存上下文(我假设您使用的是带有@ContextConfiguration的SpringJunit4Runner,但是不能确定,因为您的实际测试不在问题中)。
如果我的假设是正确的,Spring会缓存上下文,以便在运行单元测试套件的过程中提高性能。如果您的测试以影响其他测试的方式修改上下文(比如在一个需要在其他测试中再次运行的测试中运行脚本),那么您可以使用@DirtiesContext标记测试,并且Spring不会缓存上下文。您可以在方法或类级别使用注释。您可以在这里阅读更多关于注释的内容:http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/test/annotation/DirtiesContext.html
发布于 2015-01-29 16:30:47
我花了很多时间研究这个问题,并阅读了Spring文档(喘息!)并通过代码进行追踪。在4.1弹簧核中有一些有趣的变化,特别是测试。
我发现ApplicationContext(s)现在缓存在JVM级别。如果第二个测试请求一个上下文,TestContext首先在它的缓存中查找,以查看其他测试是否已经请求了相同的配置。
我有一些我的测试的简介。具有不同配置文件但相同的@ContextConfiguration的测试将导致应用配置文件重新加载该上下文。当"Bean“到达创建嵌入式数据库时,EmbeddedDatabaseFactory没有考虑到嵌入式数据库(内存中的HSQLDB)可能已经从以前的测试中创建或缓存,并且不需要重新初始化。
因此,我在EmbeddedDatabaseFactory.initDatabase()中添加了一些逻辑,在重新初始化和运行DatabasePopulator之前检查数据库是否已经存在。
List existingDataBases = org.hsqldb.DatabaseManager.getDatabaseURIs();
boolean isExisting = false;
String localDBName = StringUtils.lowerCase(this.databaseName);
for (Object object : existingDataBases) {
if (object.toString().contains(localDBName)) {
isExisting = true;
break;
}
}
// Now populate the database
if (!isExisting && this.databasePopulator != null) {(当然,这并不完全符合春天的需要,但它明白了问题的意义。)
在我看来,EmbeddedDatabaseFactory和TestContext缓存机制在一定程度上是个问题。我的"jdbc:embedded-database“定义没有任何与它们相关的配置文件。为什么缓存需要重新创建它们,而不是从现有的缓存bean中加载它们?
发布于 2016-02-24 19:35:45
每次创建新对象时,都可以使用generateUniqueName(true)设置惟一名称,从而强制创建新的嵌入式数据库。
下面是一个示例:
embeddedDatabase = new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.generateUniqueName(true)
.addScripts("db/sql/create-db.sql", "db/sql/insert-data.sql")
.build();https://stackoverflow.com/questions/28157842
复制相似问题