我可以在HSQLDB中使用CURSOR类型的OUT参数吗?

时间:2016-10-27 18:05:15

标签: java oracle unit-testing stored-procedures hsqldb

我有一个java web项目,它通过存储过程与Oracle数据库进行通信。当存储过程需要返回RecordSet时,我让存储过程接受一个SYS_REFCURSOR类型的OUT参数。然后Java代码遍历记录集以读取值。我试图对DOA层进行单元测试,然后我开始使用HSQLDB来模拟数据库,但似乎不可能在HSQLDB中使用存储过程获取OUT CURSOR参数。我以前从未使用过HSQLDB,所以请原谅我对如何使用它的无知。 以前有人处理过这个吗? 我觉得我的选择是:

  1. 使用实际允许我让存储过程执行选择的MS SQL,而不是必须使用OUT SYS_REFCURSOR将数据传递回Java代码。我更希望自己思考,我的公司不会让我使用MS SQL :(。
  2. 在PL / SQL中找到一种方法,让存储过程以Java调用者可以使用的方式返回没有OUT参数的记录。
  3. 找到HSQLDB的替代方案,它允许我在单元测试期间模拟存储过程,其行为更像Oracle。
  4. 不要打扰DOA层的单元测试。这似乎就在我最终的位置,它并不重要,因为DOA层中几乎没有任何业务逻辑在测试中具有价值,它更多的只是尝试提高我的代码覆盖率统计
  5. 作为参考,这是对存储过程的典型调用:

       private static final RowMapper<MyRecord> RECORD_ROW_MAPPER=
            (rs, i) -> new MyRecord(rs.getInteger("OWNER_ID"),
                                    rs.getString("NAME"), 
                                    rs.getString("DESCRIPTION"));
    
       private static final SimpleJdbcCall getRecordProcCall = new SimpleJdbcCall(dataSource)
                                  .withSchemaName("app_data")
                                  .withProcedureName("getMyRecords")
                                  .returningResultSet("OUT_RECORD", RECORD_ROW_MAPPER);
    
       public ArrayList<MyRecord> getMyRecords(int ownerId) {
          SqlParameterSource in = new MapSqlParameterSource()
                                  .addValue("IN_OWNER_ID", ownerId);
          return getRecordProcCall.executeFunction(ArrayList.class, in);
       }
    

    我相应的PL / SQL函数:

    CREATE PROCEDURE getMyRecords (
      IN_OWNER_ID IN  NUMBER,
      OUT_RECORD  OUT SYS_REFCURSOR
    )AS
    BEGIN
      OPEN OUT_RECORD FOR 
      SELECT OWNER_ID, NAME, DESCRIPTION
      FROM MY_RECORD
      WHERE OWNER_ID = IN_OWNER_ID;
    END
    

    我知道我可以使用直接SQL来完成这个简单的示例案例,而不是使用存储过程,但是在这篇文章中显示我如何访问数据库是很简单的。实际上,我做了大量的工作,这些工作在存储过程中做得最好。

2 个答案:

答案 0 :(得分:2)

您可以从HSQLDB存储过程中获取游标。

CREATE PROCEDURE getMyRecords (
 IN_OWNER_ID IN  NUMBER
) 
 BEGIN ATOMIC
  DECLARE MYCURSOR CURSOR FOR RETURN FOR
   SELECT OWNER_ID, NAME, DESCRIPTION
   FROM MY_RECORD
   WHERE OWNER_ID = IN_OWNER_ID;
  OPEN MYCURSOR;
 END

在JDBC方面,它应该通过使用getResultSet()和getMoreResults()调用后获取ResultSet来工作。

顺便说一句,您可以通过创建虚拟类型(例如

)来模拟过程签名
CREATE TYPE SYS_REFCURSOR AS INT;

并使用与原始程序相同的签名。

答案 1 :(得分:1)

从Oracle 12c第1版(12.1)开始,DBMS_SQL包中包含RETURN_RESULT过程,该过程将执行语句的结果返回给客户端应用程序,类似于MS SQL Server过程隐式返回记录的方式集。

ORACLE-BASE博客的Tim Hall在Implicit Statement Results in Oracle Database 12c

上有一个很好的帖子