2017-12-08 4 views
2

私は、ストアドプロシージャへのJava/JDBC呼び出しをいくつか成功させて開発しています。しかし、出力パラメータが文字列の配列である場合、私は立ち往生しています。私は入力パラメータとしてスカラ型と入力パラメータとして文字列の配列として成功しています。ここでアレイが機能するストアドプロシージャの出力パラメータを取得するにはどうすればよいですか?

は、私が持っているPL/SQLコードです:

TYPE StringArray IS TABLE OF VARCHAR2(32767) INDEX BY BINARY_INTEGER; 

create or replace package body 
test is 
    procedure upper(
    in_array  in StringArray, 
    out_array out StringArray 
) is 
    tmp StringArray := in_array; 
    begin 
    for i in 0..(tmp.count-1) loop 
     tmp(i) := UPPER(tmp(i)); 
    end loop; 
    out_array := tmp; 
    end; 
end test; 

は、ここで私が持っているJavaコードです:

public void testString(Connection connection) { 
    String[] values = { "alpha", "beta", "gamma" }; 
    try { 
     CallableStatement callableStatement = connection.prepareCall("begin test.upper(?, ?); end;"); 
     DelegatingConnection<OracleConnection> delegatingConnection = (DelegatingConnection<OracleConnection>) new DelegatingConnection(connection); 
     OracleConnection oracleConnection = (OracleConnection) delegatingConnection.getInnermostDelegate(); 
     Array input oracleConnection.createOracleArray("STRINGARRAY", values); 
     callableStatement.setObject("in_array", input); 
     callableStatement.registerOutParameter("out_array", Types.ARRAY, "STRINGARRAY"); 
     callableStatement.execute(); 
     Array output = (Array)callableStatement.getObject("out_array"); 
     String[] result = (String[])output.getArray(); 
     System.out.println("Length: " + result.length); // Prints "Length: 3" 
     System.out.println("First: " + result[0]);  // Prints "First: null" 
    } (catch SQLException e) { 
     // Handle error 
    } 
} 

私はSQLスクリプトからPL/SQLストアドプロシージャを呼び出す場合、直接それが動作します。だから私はストアドプロシージャ自体は大丈夫だと思います。

JDBC経由でストアドプロシージャを呼び出すと、正常に完了します。デバッグステートメントを使用して、valuesが正しくJavaクライアントからストアドプロシージャにin_arrayに送信されていることを確認しました。つまり、適切な値を持つ長さ3の配列が受け取られます。私が知る限り、​​がJavaクライアントに返送されます。しかし、何かが間違っています。 resultのサイズは3ですが、すべての要素はnullです。

outputを調べると、内部では長さがbyte[]であることがわかります。これらのバイトのサブシーケンスは、「アルファ」、「ベータ」、「ガンマ」に対応しています。したがって、データはクライアントに返されるように見えますが、正しくString[]に変換されません。

私は間違っていますか?

+0

実際に直面している問題はどこですか。 PLSQLブロックまたはJAVA呼び出し。あなたの質問から明らかではない – XING

+0

@XINGわかりやすいように、ストアドプロシージャが正常に完了するとPL/SQLは大丈夫です。しかし、Javaクライアントコードでは、結果は正しい長さの配列であり、 'null'要素で構成されます。したがって、データはクライアント側で正しく変換されていません。これに基づいて、問題はJavaの終わりにあると思うが、あなたは決して知らない。 – dave

+0

連想配列(インデックスによるテーブル)ではなく、可変配列またはネストしたテーブルを使用することがあります。彼らは[documentation](https://docs.oracle.com/database/121/JJDBC/oraarr.htm#JJDBC28574)に、JDBCドライバがvarrarrayとネストした表をサポートしていると書いています。ドキュメンテーション。 – krokodilko

答えて

2

連想配列を使用しないでください - コレクションを使用します。

CREATE TYPE StringArray IS TABLE OF VARCHAR2(4000); 
CREATE TYPE CLOBArray IS TABLE OF CLOB; 

次に、あなたが行うことができます:

public void testString(Connection connection) { 
    String[] values = { "alpha", "beta", "gamma" }; 
    try { 
    OracleConnection oc = (OracleConnection) connection; 

    ARRAY stringArray = oc.createARRAY("STRINGARRAY", values); // Upper case identifier 

    OracleCallableStatement st = (OracleCallableStatement) oc.prepareCall(
     "begin test.upper(:in_array, :out_array); end;" 
    ); 

    st.setARRAYAtName("in_array", stringArray); 
    st.registerOutParameter("out_array", Types.ARRAY, "STRINGARRAY"); // Upper case again 
    st.execute(); 

    String[] result = (String[])st.getARRAY(2).getArray(); 

    System.out.println("Length: " + result.length); 
    System.out.println("First: " + result[0]); 
    } (catch SQLException e) { 
    // Handle error 
    } 
} 

を、あなたの手順への入力としてPL/SQL連想配列を使用する必要がある場合コレクションをとり、適切な型の連想配列を出力する関数を記述し、それを呼び出します。

BEGIN TEST.UPPER(TO_ASSOC_ARRAY(:in_collection), :out_array); END; 

注:この回答は、OracleConnection.createOracleArray() methodが表示されていないojdbc6.jarのOracleドライバを使用していることを前提としていますが、うまくいけばポータブルでoracle.sql.ARRAYからjava.sql.Arrayに変更し、新しい方法を使用します。

+0

私は 'ojdbc7 'を使っていると確信しています。瓶。それは問題だろうか?あなたは答えを変えますか? – dave

+0

キーチップ - 連想配列を使用しない - 私の問題を解決するのに役立ちました。 'out_array'の型を変更するだけで、ストアドプロシージャから文字列の配列を受け取ることができました。 Javaクライアントコードを変更する必要はありませんでした。 – dave

関連する問題