oracle 如何从 Java 类中调用带有 out 参数作为表类型的过程

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11621638/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 04:20:40  来源:igfitidea点击:

How to call procedure with out parameter as table type from a Java class

oraclejdbcplsqloracle11g

提问by ashok_p

I want to call this procedure get_data_Q1in the package ult_pkgfrom Java code and display the output:

我想从 Java 代码get_data_Q1的包中调用这个过程ult_pkg并显示输出:

CREATE OR REPLACE PACKAGE  ult_pkg
AS
TYPE t_all_record is record (
    x_object_type_id        number,
    x_object_name           varchar2(100),
    x_object_id             varchar2(70),
    x_audit_timestamp       timestamp(6),
    x_payload               clob
);

--table type to hold table data after querying

type tt_all_tab is table of t_all_record index by binary_integer;

--declaration pocedures
procedure get_data_Q1(x_object_id in varchar2 , x_all_type out tt_all_tab );


end ult_pkg;

/

--body of 'ult_pkg'  package
create or replace package body ult_pkg 
AS

    --procedure taking 'object_id' as input parameter and gives out table of 't_all_record' type 
    procedure get_data_Q1(x_object_id in varchar2 , x_all_type out tt_all_tab )
    AS

        i number:=0;
    begin

    for r in 
        ( 
            SELECT
            O.object_type_id,O.object_name,O.object_id,A.audit_timestamp,P.payload
            FROM
            APPLICATION APP, EXCEPTIONS E,MASTER_AUDIT A,MODULE_TYPE M,OBJECT_TYPE O,PAYLOAD P 
            WHERE 
            ( A.MODULE_TYPE_ID = M.MODULE_TYPE_ID ) AND ( M.APPLICATION_ID = APP.APPLICATION_ID ) AND ( A.OBJECT_TYPE_ID = O.OBJECT_TYPE_ID ) AND ( O.OBJECT_ID = x_object_id )
        )
    -- loop to asign the data from cursor 'r' to carasponding table type columns
        loop


        x_all_type(i).x_object_type_id:=r.object_type_id;
        x_all_type(i).x_object_name:=r.object_name;
        x_all_type(i).x_object_id:=r.object_id;
        x_all_type(i).x_audit_timestamp:=r.audit_timestamp;
        x_all_type(i).x_payload:=r.payload;
        i:=i+1;
        end loop;

    end get_data_Q1;
end ult_pkg;
/

回答by Michael Simons

This not possible, see Accessing PL/SQL Index-by Tables:

这是不可能的,请参阅访问 PL/SQL 索引表

Oracle JDBC does not support RAW, DATE, and PL/SQL RECORD as element types.

Oracle JDBC 不支持 RAW、DATE 和 PL/SQL RECORD 作为元素类型。

I'd probably use a custom (global, not package) object type like so:

我可能会使用自定义(全局,而不是包)对象类型,如下所示:

CREATE TYPE t_all_record AS OBJECT (
  x_object_type_id        number,
    x_object_name           varchar2(100),
    x_object_id             varchar2(70),
    x_audit_timestamp       timestamp(6),
    x_payload               clob
)
/
CREATE TYPE t_all_records IS TABLE OF t_all_record
/

reference the table of type in your package (t_all_records instead of tt_all_tab) and fill it like so

引用包中的类型表(t_all_records 而不是 tt_all_tab)并像这样填充它

procedure get_data_Q1(x_object_id in varchar2 , x_all_type out t_all_records )
AS
begin
    SELECT t_all_record(O.object_type_id,O.object_name,O.object_id,A.audit_timestamp,P.payload)
    BULK COLLECT INTO x_all_type
    FROM APPLICATION APP, EXCEPTIONS E,MASTER_AUDIT A,MODULE_TYPE M,OBJECT_TYPE O,PAYLOAD P 
    WHERE ( A.MODULE_TYPE_ID = M.MODULE_TYPE_ID ) AND ( M.APPLICATION_ID = APP.APPLICATION_ID ) AND ( A.OBJECT_TYPE_ID = O.OBJECT_TYPE_ID ) AND ( O.OBJECT_ID = x_object_id )
end get_data_Q1;

Result will be useable from java like so:

结果将可以从 java 中使用,如下所示:

package tests.jdbc;

import java.sql.Array;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSetMetaData;
import java.sql.Struct;
import java.sql.Types;

import oracle.sql.StructDescriptor;

public class OracleTableOfResult {
    public static void main(String...a) throws Exception {
        Class.forName("oracle.jdbc.OracleDriver");
        Connection connection = DriverManager.getConnection("jdbc:oracle:thin:<USER>/<PASS>@<DATABASEHOST>:1521:<SERVICE>");

        final String typeName = "T_ALL_RECORD";
        final String typeTableName = "T_ALL_RECORDS";

        // Get a description of your type (Oracle specific)
        final StructDescriptor structDescriptor = StructDescriptor.createDescriptor(typeName.toUpperCase(), connection);        
        final ResultSetMetaData metaData = structDescriptor.getMetaData();

        // Call the procedure (or whatever else) that returns the table of a custom type
        CallableStatement cs = connection.prepareCall("{call ult_pkg.get_data_Q1(?, ?)}");
        cs.setString(1, "the_id");
        // Result is an java.sql.Array...
        cs.registerOutParameter(2, Types.ARRAY, typeTableName);     
        cs.execute();

        // ...who's elements are java.sql.Structs
        Object[] data = (Object[]) ((Array) cs.getObject(2)).getArray();
        for(Object tmp : data) {
            Struct row = (Struct) tmp;
            // Attributes are index 1 based...
            int idx = 1;
            for(Object attribute : row.getAttributes()) {               
                System.out.println(metaData.getColumnName(idx) + " = " + attribute);                                            
                ++idx;
            }
            System.out.println("---");
        }
        cs.close();     
        connection.close();
    }
}

But in the end, it's questionable if it's worth the effort when you could use your query in a plain sql statement as a prepared statement…

但最终,当您可以在普通 sql 语句中使用查询作为准备好的语句时,是否值得付出努力是值得怀疑的……