我目前正在尝试使用使用 Spring 创建的内存 HSQLDB 实例创建一个测试环境,这要归功于它的嵌入式数据库支持:
当前设置
为我的单元测试创建“数据源”:
db = new EmbeddedDatabaseBuilder() .addDefaultScripts() .addScript("stored_procedure.sql") .build();
“stored_procedure.sql”的内容:
-- Mock of a more complex stored procedure in production environment CREATE PROCEDURE GetFooById(IN fooId VARCHAR(12)) READS SQL DATA DYNAMIC RESULT SETS 1 BEGIN ATOMIC DECLARE resultSet CURSOR WITHOUT HOLD WITH RETURN FOR SELECT name, value FROM Foos WHERE id = fooId; OPEN resultSet; END
问题
我能够初始化我的模式并从“默认脚本”插入我的测试数据,没有任何问题。
但是,在创建过程时,我看到如下错误,即使在上述 SQL 的不同版本之后,有/没有分隔符,并且分隔符在不同的位置:
java.sql.SQLSyntaxErrorException: unexpected end of statement: required: ; at org.hsqldb.jdbc.Util.sqlException(Unknown Source) at org.hsqldb.jdbc.Util.sqlException(Unknown Source) at org.hsqldb.jdbc.JDBCStatement.fetchResult(Unknown Source) at org.hsqldb.jdbc.JDBCStatement.executeUpdate(Unknown Source) at org.springframework.jdbc.datasource.init.ResourceDatabasePopulator.executeSqlScript(ResourceDatabasePopulator.java:169)
资源和提示
我正在使用提供 HSQLDB 2.2.4 的 Spring 3.1.1,并且根据文档,我认为我在做正确的事情。
但是,讨论如下:
- 这个
- 春天的 JIRA 票 SPR-8817
让我觉得这可能是 HSQLDB 和 Spring 之间的不兼容/由处理分隔符的方式引起的错误。
但我是 Spring 和 HSQLDB 的初学者,因此我有以下问题。
问题
有人见过这个吗?并提出了解决方案?
考虑到最终的存储过程是使用{call GetFooById ?} 调用的,是否有一种等效的方法可以在 HSQLDB 中使用 select-from-where 查询返回结果集?
这会因为 ResourceDatabasePopulator 而有效地发生吗?ResourceDatabasePopulator 是否仍然在 Spring 3.1.1 中造成麻烦?
任何其他指针/提示?
非常感谢您的帮助。
M。
编辑:
结论与解决方案
问题:
ResourceDatabasePopulator 将分号处理为查询分隔符,这不符合 HSQLDB 的语法。
{call GetFooById ?}是 Sybase(我的生产数据库)的有效语法,但不适用于需要{call GetFooById(?)}的 HSQLDB 。当然,HSQLDB 语法也不兼容 Sybase 的语法。此外,Spring 的 JdbcTemplate 并没有抽象出这些差异。
解决方案:
使用 Java 存储过程而不是 SQL 存储过程可能是一种解决方法,因为查询是在 Java 端编写的,并且不涉及分号分隔符。或者,我猜 ResourceDatabasePopulator 的逻辑可以更改并用于设置嵌入式数据库,但到目前为止我还没有尝试过。
Spring 的 StoredProcedure 类似乎更便携,可以与 Sybase 和 HSQLDB 一起使用,即使它比 JdbcTemplate 更冗长。
源代码:在我的 GitHub 存储库中可用。