【发布时间】:2017-03-10 12:56:44
【问题描述】:
我有一个通过存储过程与 Oracle 数据库通信的 Java Web 项目。当存储过程需要返回 RecordSet 时,我让存储过程接受 SYS_REFCURSOR 类型的 OUT 参数。然后,Java 代码遍历记录集以读取值。我正在尝试对 DOA 层进行单元测试,并开始使用 HSQLDB 来模拟数据库,但似乎不可能在 HSQLDB 中存储一个带有 OUT CURSOR 参数的过程。我以前从未使用过 HSQLDB,所以请原谅我对如何使用它的无知。 以前有没有人处理过这个问题? 我觉得我的选择是:
- 使用实际上允许我让存储过程执行选择的 MS SQL,而不必使用 OUT SYS_REFCURSOR 将数据传回 Java 代码。这是我更希望的想法,我的公司不会让我使用 MS SQL :(。
- 在 PL/SQL 中找到一种方法,让存储过程以 Java 调用者可以使用的方式返回不带 OUT 参数的记录。
- 找到 HSQLDB 的替代方案,让我在单元测试期间模拟存储过程,其行为更像 Oracle。
- 不要费心对 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