如何在HSQLDB中定义Out CURSOR并通过Java / Junit访问它

问题描述

我有一个Java Web项目,该项目通过存储过程与Oracle数据库对话。存储的proc接受类型为SYS_REFCURSOR的两个输入和1个OUT参数。然后,Java代码遍历记录集以读取值。我正在尝试对DOA层进行单元测试,并且我开始使用HsqlDB来模拟数据库,但似乎不可能在HsqlDB中使用OUT CURSOR参数在proc中存储存储过程。

我参考了以下帖子Can I have an OUT parameter of type CURSOR in HSQLDB?,并通过创建虚拟类型创建了模拟过程签名。但是,当访问结果时,我面临问题。我得到空结果集。如何在Java中访问游标输出。 (注意:访问真实数据库时,一切工作正常)

PL / sql功能

PROCEDURE sp_get_first_time_code_partid (
    i_partid          IN     NUMBER,p_delivery_code   IN     VARCHAR2,ret_recordset        OUT SYS_REFCURSOR)
....
....
END sp_get_first_time_code_partid;

Java程序

  public void populateFirstTimeCodeInfo(CallableStatement callableStatement) throws sqlException
  {
    ResultSet resultSet = (ResultSet) callableStatement.getobject(3);
    while (resultSet.next())
    {
      System.out.println(resultSet.getString("SSN_NUM"));
    }
  }

Junit测试用例

statement.execute(
        "create table PKG_ARO_FirsT_TIME_CODE.ARO_FirsT_TIME_CODE (ssn_num VARCHAR2,create_date VARCHAR(30) NOT NULL,first_time_code VARCHAR(20) NOT NULL,"
                + "code_sent_source VARCHAR(10) NOT NULL,code_expire_date VARCHAR(10) NOT NULL)");

statement.executeUpdate(
        "insert into PKG_ARO_FirsT_TIME_CODE.ARO_FirsT_TIME_CODE (ssn_num,create_date,first_time_code,code_sent_source,code_expire_date) values ('894463762','2/13/2019 11:03:02 AM',"
                + "'WMKNSMWY','C','2/19/2019')");

虚拟类型

statement.execute("CREATE TYPE SYS_REFCURSOR AS VARCHAR2;");

具有虚拟类型的模拟存储过程

statement.execute(
"CREATE PROCEDURE SSADMIN.PKG_ARO_FirsT_TIME_CODE.SP_GET_FirsT_TIME_CODE_PARTID(IN i_part_id VARCHAR2,IN p_delivery_code VARCHAR2,OUT ret_recordset SYS_REFCURSOR)\r\n"
 + READS sql DATA DYNAMIC RESULT SETS 1\r\n + BEGIN ATOMIC\r\n +
 "DECLARE ret_recordset CURSOR WITH RETURN FOR SELECT * FROM PKG_ARO_FirsT_TIME_CODE.ARO_FirsT_TIME_CODE;\r\n"
 + "open ret_recordset;\r\n" + "END");

执行时

ResultSet resultSet = (ResultSet) callableStatement.getobject(3);

resultSet为空

如果我将“ READS sql DATA DYNAMIC RESULT SETS 1”替换为“ READS sql DATA”,我会得到 java.lang.classCastException:org.hsqldb.result.Result无法转换为java.sql.ResultSet

解决方法

您的OUT参数将不包含过程打开的CURSOR(仅在模拟对Oracle DB的调用时才需要此参数)。您需要准备对过程的调用,执行它,然后使用getResultSet():

 Connection conn = ...;
 CallableStatement call = conn.prepareCall("call sp_get_first_time_cod_partid(?,?)");
 call.setString(1,"val1");
 call.setString(2,"val2");
 call.execute();
 ResultSet result = call.getResultSet();

它在《指南》中有记录:http://hsqldb.org/doc/2.0/guide/sqlroutines-chapt.html#src_returning_data