Oracle 如何从Java类中调用out参数为表类型的过程
我想从Java代码调用包Oracle 如何从Java类中调用out参数为表类型的过程,oracle,jdbc,plsql,oracle11g,Oracle,Jdbc,Plsql,Oracle11g,我想从Java代码调用包ult\u pkg中的这个过程get\u data\u Q1,并显示输出: 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
ult\u pkg
中的这个过程get\u data\u Q1
,并显示输出:
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;
/
这是不可能的,请参见:
Oracle JDBC不支持将原始、日期和PL/SQL记录作为元素类型
我可能会使用自定义(全局,而不是包)对象类型,如下所示:
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
/
参考包中的类型表(t_all_记录而不是tt_all_选项卡),并像这样填充它
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;
结果将可从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();
}
}
package tests.jdbc;
导入java.sql.Array;
导入java.sql.CallableStatement;
导入java.sql.Connection;
导入java.sql.DriverManager;
导入java.sql.ResultSetMetaData;
导入java.sql.Struct;
导入java.sql.Types;
导入oracle.sql.StructDescriptor;
公共类OracleTableOfResult{
公共静态void main(字符串…a)引发异常{
类forName(“oracle.jdbc.OracleDriver”);
Connection-Connection=DriverManager.getConnection(“jdbc:oracle:thin://:1521:”;
最终字符串typeName=“T\u ALL\u记录”;
最终字符串typeTableName=“T_所有记录”;
//获取您的类型描述(特定于Oracle)
final StructDescriptor StructDescriptor=StructDescriptor.createDescriptor(typeName.toUpperCase(),connection);
最终结果SetMetadata元数据=structDescriptor.getMetaData();
//调用返回自定义类型表的过程(或任何其他过程)
CallableStatement cs=connection.prepareCall({call ult\u pkg.get\u data\u Q1(?)});
cs.设置字符串(1,“id”);
//结果是一个java.sql.Array。。。
cs.registerOutParameter(2,Types.ARRAY,typeTableName);
cs.execute();
//…谁的元素是java.sql.Structs
对象[]数据=(对象[])((数组)cs.getObject(2)).getArray();
对象(tmp:数据){
结构行=(结构)tmp;
//属性是基于索引1的。。。
int-idx=1;
对于(对象属性:row.getAttributes()){
System.out.println(metaData.getColumnName(idx)+“=”+属性);
++idx;
}
System.out.println(“--”);
}
cs.close();
connection.close();
}
}
但最终,当您可以在一个简单的sql语句中使用查询作为一个准备好的语句时,是否值得付出努力是值得怀疑的…嘿,伙计们,看起来Oracle自其版本12c Release 1以来增加了对内部包类型的支持。请看这里: