【问题标题】:HsqlException: General Error when calling a stored procedureHsqlException:调用存储过程时出现一般错误
【发布时间】:2020-02-15 00:21:50
【问题描述】:

我正在尝试为调用存储过程的 DAO 编写集成测试。我从一个测试文件创建了一个嵌入式 HSQL 数据库,该文件只是创建一个表、填充它,以及一个返回表结果的简单存储过程:

CREATE PROCEDURE usp_GetAvailableServices()
READS SQL DATA
BEGIN ATOMIC
    DECLARE result CURSOR WITH RETURN FOR SELECT FeatureType FROM PUBLIC.service_areas ;
    OPEN result;
END/;

创建数据库的代码如下。数据库已正确创建和填充。

        db = new EmbeddedDatabaseBuilder()
                .setType(EmbeddedDatabaseType.HSQL)
                .addScript("db/sql/getAvailableServicesStoredProcedure.sql")
                .setSeparator("/;")
                .build();

尝试使用General error; nested exception is java.sql.SQLException: General error 调用存储过程时我的测试失败,这最终是由

Caused by: org.hsqldb.HsqlException: General error
    at org.hsqldb.error.Error.error(Unknown Source)
    at org.hsqldb.error.Error.error(Unknown Source)
    ...

我让 HSQLDB 控制台运行并确认我的存储过程确实已创建(它在information_schema.routines 下列出),但是当我尝试使用call usp_GetAvailableServices() 直接在控制台中调用存储过程时,我仍然看到General error / Error Code: -458 / State: S1000

这让我相信我的创建过程语法有错误(根据http://hsqldb.org/doc/2.0/guide/sqlroutines-chapt.html#src_psm_cursors 似乎是正确的),或者我不知道如何正确调用 HSQLDB 中的例程。

使用 SqlServer 调用实时存储过程的代码可以正常工作。只有 HSQLDB 不起作用。

【问题讨论】:

    标签: java stored-procedures hsqldb


    【解决方案1】:

    您的程序很好。因为它使用OPEN cursorname CURSOR,所以不能用DatabaseManager 或SqlTool 调用它。您需要使用 JDBC 使用 execute() 以这种方式调用它:

        CallableStatement cs = conn.prepareCall(
            "call usp_GetAvailableServices()");
        boolean isResult = cs.execute();
    
        assertFalse(isResult);
    
        isResult = cs.getMoreResults();
    
        ResultSet rs = cs.getResultSet();
    
        rs.next();
        // do something with the rs row
        rs.close();
    

    注意调用 getMoreResults() 的必要性。

    或者,使用 executeQuery() 来避免额外的调用。

        CallableStatement cs = conn.prepareCall(
            "call usp_GetAvailableServices()");
    
        ResultSet rs = cs.executeQuery();
    
        rs.next();
        // do something with the rs row
        rs.close();
    

    下一个版本,目前可作为来自http://hsqldb.org/downlaod 的快照 jar 使用,支持 cs.execute() 和 cs.getResultSet() 而没有 cs.getMoreResults()。

        CallableStatement cs = conn.prepareCall(
            "call usp_GetAvailableServices()");
        boolean isResult = cs.execute();
    
        ResultSet rs = cs.getResultSet();
    
        rs.next();
        // do something with the rs row
        rs.close();
    

    【讨论】:

    • 谢谢,这有助于我理解问题。规定的解决方案对我不起作用,因为它需要我更改正在测试的代码。是否可以在没有游标的情况下在存储过程中返回查询的结果集?我的数据集总是很小。
    • 请将适用于 SqlServer 的 Java 代码添加到您的问题中。
    • 我能够使用此处提供的信息回答我的问题。问题确实是光标。 HSQLDB 不能在没有游标的情况下返回 ResultSet,但是函数可以返回一个表,该表可以在不使用游标的情况下模拟实际存储过程的行为。
    猜你喜欢
    • 2015-08-16
    • 2018-02-09
    • 1970-01-01
    • 2018-11-13
    • 2016-11-10
    • 1970-01-01
    • 2015-10-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多