在某些参数类型是用户定义的情况下,如何使用 JDBC/Spring 调用 Oracle 存储过程?

Posted

技术标签:

【中文标题】在某些参数类型是用户定义的情况下,如何使用 JDBC/Spring 调用 Oracle 存储过程?【英文标题】:How can I call an Oracle stored procedure with JDBC/Spring where some of the parameter types are user defined? 【发布时间】:2010-08-17 09:32:08 【问题描述】:

我正在尝试从我的 Java 程序中调用 Oracle 存储过程。我正在使用 JDBC 和 Spring 的 StoredProcedure。有几个参数是用户定义的类型,我需要知道如何传递它们。

特别是我应该在参数映射中指定什么类型(即java.sql.Types.* 中的哪一个)?我应该使用什么 Java 类型?问题类型定义如下:

type MyDoubles as varray(50000) of double precision
type MyStrings as varray(50000) of varchar2(2000)

【问题讨论】:

【参考方案1】:

Google 中的第一个热门似乎展示了如何绑定 VARRAY 类型的参数:http://www.devx.com/tips/Tip/22034。本文档中的示例使用预准备语句,但对于存储过程,它的工作方式应该相同。

这是一个显示基本概念的摘录:

字符串数组元素[] =  "Test3", "Test4" ;
PreparedStatement ps =
    conn.prepareStatement("插入到 sample_varray_table 值 (?)");

ArrayDescriptor desc = ArrayDescriptor.createDescriptor("STRING_VARRAY", conn);
数组 newArray = new ARRAY(desc, conn, arrayElements);
((OraclePreparedStatement)ps).setARRAY (1, newArray);

ps.execute();

为了澄清这里有几个 FQDN:

oracle.sql.ArrayDescriptor oracle.sql.ARRAY oracle.jdbc.OraclePreparedStatement

【讨论】:

【参考方案2】:

为什么用户传递 50,000 个双精度和字符串实例 - 以便 Oracle 可以执行计算?

这对我来说似乎倒退了。如果用户已经拥有了一整天的时间,也许 Java 可以执行该计算。如果您真的希望 Oracle 这样做,我会说数据应该已经驻留在数据库中而不是传入。

不会都是 java.sql.Type.ARRAY 吗?

【讨论】:

我能想到一个原因 - 在应用程序中构建数组,将数组传递给 PL/SQL 过程以使用 FORALL 执行批量 PL/SQL 操作。但是,我会使用 TABLE OFVARRAY(50000) 来获得灵活性,但这只是我自己。 数据库可以执行哪些在服务器端无法完成的操作,而不会产生来回的网络流量成本?如果这是一个长时间运行的过程,我希望它是异步的,无论它在哪里完成。仍然没有意义。【参考方案3】:

您确实可以按照 Philipp 的建议使用 Oracle JDBC 驱动程序中的对象。大多数用户最终会创建实用程序方法来包装该逻辑。或者他们使用 Spring 映射器类。不过,还有很多手工工作要做。

另一种方法是使用即将推出的jOOQ 1.5.4 版——我正在开发的一个开源库——统一支持数组。所以当你有你的类型时:

type MyDoubles as varray(50000) of double precision
type MyStrings as varray(50000) of varchar2(2000)

然后jOOQ会生成诸如

之类的类
public class MyDoubles extends ArrayRecordImpl<Double>  /* ... */ 
public class MyStrings extends ArrayRecordImpl<String>  /* ... */ 

您的存储过程可能如下所示:

PROCEDURE MY_PROC1 (d IN  MyDoubles, s IN  MyStrings);
PROCEDURE MY_PROC2 (d IN  MyDoubles, s OUT MyStrings);
PROCEDURE MY_PROC3 (d OUT MyDoubles, s OUT MyStrings);

而 jOOQ 会生成另一个 Java 类,例如

public class Procedures 

    // Invoke procedure MY_PROC on JDBC Connection c with VARRAY arguments
    public static void myProc1(Connection c, MyDoubles d, MyStrings s);

    // The OUT parameter is mapped to a method return value
    public static MyStrings myProc2(Connection c, MyDoubles d);

    // MyProc3 is a wrapper for both OUT parameters
    public static MyProc3 myProc3(Connection c);

使用生成的代码工件,调用带有 UDT、VARRAY 参数的存储过程非常简单。通过源代码生成,您可以更改数据库模式中的对象(例如您的类型或过程),您的 Java 类将立即反映该更改。

查看手册http://www.jooq.org/manual/META/PROCEDURE/了解更多详情

【讨论】:

以上是关于在某些参数类型是用户定义的情况下,如何使用 JDBC/Spring 调用 Oracle 存储过程?的主要内容,如果未能解决你的问题,请参考以下文章

如何在不定义内容类型或模型的情况下使用 Django 权限?

如何在运行时更改JMeter的负载

EXCEL函数内部的嵌套函数

如何在没有参数的情况下快速将类保存到用户默认值

如何在不更改输入内容的情况下更改输入值

创建未知类型的数组。 C#