2016-09-27 15 views
0

JDBCから次のpl/sqlプロシージャをコールしようとしています。Oracle JDBC呼び出しPL/SQLプロシージャ(入力パラメータ付き)レコード表

create or replace PACKAGE test AS 

type testrec_r is record (
val1 number, 
val2 varchar2(100) 
); 

type testarr_t is table of testrec_r index by binary_integer; 

function test_func(i_data in testarr_t, o_sum out number, o_totallength out  number) return number; 

END test; 

これは私が成功せず、それを起動しようとした方法である:

StructDescriptor recDescriptor = StructDescriptor.createDescriptor("test.testrec_r", conn); 
    STRUCT[] RECORDS_ARRAY = new STRUCT[2]; 

    for (int i = 0; i < 2; i++) { 
     STRUCT oracle_record = new STRUCT(recDescriptor, conn, new 
     Object[] {i, "test"}); 
     RECORDS_ARRAY[i] = oracle_record; 
    } 

    CallableStatement stmt = conn.prepareCall("{ call TEST.TEST_FUNC(?, ?, ?) }"); 

    ArrayDescriptor arrayDescriptor = ArrayDescriptor.createDescriptor("TEST.TESTARR_T", conn); 
    ARRAY oracle_array = new ARRAY(arrayDescriptor, conn, RECORDS_ARRAY); 

    // Bind the input record 
    stmt.setArray(1, oracle_array); 
    stmt.registerOutParameter(2, Types.NUMERIC); 
    stmt.registerOutParameter(3, Types.NUMERIC); 
    stmt.executeUpdate(); 
    double out1 = stmt.getDouble(2); 
    double out2 = stmt.getDouble(3); 
    return new Object[] { out1, out2 }; 

私はOracleのJDBCは、PL/SQL構造体の種類をサポートしていないことを読みました。したがって、これは "無効な名前パターン:test.testrec_r"で失敗します

Javaからこのプロシージャを呼び出す方法はありますか。理想的には、Javaのlibray/APIを使用するだけですが、これはほとんど不可能なようです。これは単純なSQL呼び出しでpl/sqlパッケージをラップして呼び出す最良の回避策ですか?

P.私は、データベース接続にSpring JDBCTemplateを使用しています。

答えて

0

PLSQLタイプは、PLSQLタイプのみを使用することはできません(12c以降、これは厳密には真ではありません - UPD2を参照)。また、パッケージ内で作成されたすべての型はjavaによって直接表示されません。
スキーマレベルでSQL型を作成する必要があります。 SQL型はすべてが見ることができ、すべてが使用できる。

create or replace and compile java source named "ArrayOfRecTest" as 
import java.io.*; 
import java.sql.*; 
import oracle.sql.*; 
import oracle.jdbc.driver.*; 

public class ArrayOfRecTest 
{ 
    public static void passArrayOfRec() throws SQLException 
    { 
     Connection conn = new OracleDriver().defaultConnection(); 

     StructDescriptor sd = StructDescriptor.createDescriptor("MYREC_TYPE", conn); 
     ArrayDescriptor ad = ArrayDescriptor.createDescriptor("MYRECARR_TYPE", conn); 
     STRUCT[] recarr = new STRUCT[2]; 
     for (int i = 0; i < 2; i++) { recarr[i] = new STRUCT(sd, conn, new Object[] {i+1, "value " + (i+1)}); } 
     ARRAY oracle_array = new ARRAY(ad, conn, recarr); 

     CallableStatement stmt = conn.prepareCall("{ ? = call testpkg.showArrOfRec(?, ?, ?) }"); 
     stmt.registerOutParameter(1, Types.INTEGER); 
     stmt.setObject(2, oracle_array); 
     stmt.registerOutParameter(3, Types.INTEGER); 
     stmt.registerOutParameter(4, Types.INTEGER); 

     stmt.execute(); 
     int sizeofArr = stmt.getInt(1); 
     int total = stmt.getInt(3); 
     int totalLength = stmt.getInt(4); 
     System.out.println("passArrayOfRec(total,len)=(" + total + "," + totalLength + ") " + sizeofArr + " records were shown"); 
    } 
} 
/

create or replace force type myrec_type as object(id number, value varchar2(100)); 
/
create or replace type myrecarr_type as table of myrec_type; 
/

create or replace package testpkg as 
    procedure passArrayOfRec as language java name 'ArrayOfRecTest.passArrayOfRec()' ; 
    function showArrOfRec(ra myrecarr_type, total out number, totallength out number) return number; 
end testpkg; 
/

create or replace package body testpkg as 
    --OP stuff 
    type testrec_r is record (val1 number, val2 varchar2(100)); 
    type testarr_t is table of testrec_r index by binary_integer; 
    function test_func(data in testarr_t, total out number, totallength out number) return number is 
    begin 
     <<for_each>> for i in data.first..data.last loop 
      dbms_output.put_line('data(' || i || ')[val1,val2]=[' || data(i).val1 || ',' || data(i).val2 || ']'); 
      total := nvl(total,0) + data(i).val1; 
      totallength := nvl(totallength,0) + length(data(i).val2); 
     end loop for_each; 
     return data.count; 
    end test_func; 
    --end OP stuff 

    function showArrOfRec(ra myrecarr_type, total out number, totallength out number) return number is 
     data testarr_t; 
    begin 
     for i in ra.first..ra.last loop data(i).val1 := ra(i).id; data(i).val2 := ra(i).value; end loop; 
     return test_func(data, total, totalLength); 
    end showArrOfRec; 
end testpkg; 
/

exec testpkg.passArrayOfRec; 
--output 
data(1)[val1,val2]=[1,value 1] 
data(2)[val1,val2]=[2,value 2] 
passArrayOfRec(total,len)=(3,14) 2 records were shown 

UPD1 showArrOfRecは、入力パラメータのPL/SQLタイプとTEST_FUNC呼び出します。

UPD2 New in 12c: More PL/SQL-Only Data Types Can Cross PL/SQL-to-SQL Interface

+0

@ csm86この関数は何を返すべきですか?あなたの質問で私は機能が何を参照してくださいない。 – 0xdb

+0

申し訳ありませんが、私は最後のコメントを誤って削除しました。これは配列の長さを返すダミー関数で、出力パラメータに数値の合計と文字列の長さを出力します。それは私が単純なSQLで取得したいものです。 – csm86

+0

@ csm86 [OK]を、関数呼び出しで更新しました。総計は大きな問題ではありません。 – 0xdb

関連する問題