问题描述
我有一个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中访问游标输出。 (注意:访问真实数据库时,一切工作正常)
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