【问题标题】:Can I have an OUT parameter of type CURSOR in HSQLDB?我可以在 HSQLDB 中有一个 CURSOR 类型的 OUT 参数吗?
【发布时间】:2017-03-10 12:56:44
【问题描述】:

我有一个通过存储过程与 Oracle 数据库通信的 Java Web 项目。当存储过程需要返回 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 层中几乎没有对测试有价值的业务逻辑,它更多的是试图改善我的代码覆盖率统计数据。

作为参考,这里是对存储过程的典型调用:

   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 来完成这个简单的示例案例而不使用存储过程,但是在这篇文章中展示我如何访问数据库只是微不足道的。实际上,我正在做大量最好在存储过程中完成的工作。

【问题讨论】:

  • 如果您使用的是 Oracle 12c,您可以利用 DBMS_SQL.RETURN_RESULT 来模仿 MS SQL 从存储过程返回 implicit record sets 的方式。
  • 这听起来像是可行的,我必须仔细阅读它。谢谢!
  • 哨兵,这行得通。如果您将此作为答案重新提交,我将接受它作为答案。

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


【解决方案1】:

您可以从 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;

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

【讨论】:

    【解决方案2】:

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

    ORACLE-BASE 博客的 Tim Hall 在Implicit Statement Results in Oracle Database 12c 上发表了一篇精彩的文章

    【讨论】:

      猜你喜欢
      • 2016-04-19
      • 2017-05-10
      • 1970-01-01
      • 1970-01-01
      • 2020-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多