4

copyFile(String, String)メソッドを定義する Java クラスがあるとします。

public class FileSystem {

    public static void copyFile(String sourcePath, String destinationPath)
        throws IOException
    {
        // ignore the fact that I'm not properly managing resources...
        FileInputStream source = new FileInputStream(sourcePath);
        FileOutputStream destination = new FileOutputStream(destinationPath);

        copyStream(source, destination);

        source.close();
        destination.close();
    }

    private static void copyStream(InputStream source, OutputStream destination)
        throws IOException
    {
        byte[] buffer = new byte[1024];

        int length;
        while ( (length = source.read(buffer)) != -1 ) {
            destination.write(buffer, 0, length);
        }
    }

}

そして、これを Java ストアド プロシージャでラップするとします。

CREATE PROCEDURE copy_file (source_path VARCHAR2, destination_path VARCHAR2)
AS LANGUAGE JAVA
NAME 'FileSystem.copyFile(String, String)';

copy_fileここで、ストアド プロシージャを呼び出すと、JavaIOExceptionがスローされます。

BEGIN
  copy_file( '/some/file/that/does/not/exist.txt', '/path/to/destination.txt' );
END;

PL/SQL ブロックで発生したエラーは次のとおりです。

ORA-29532: キャッチされていないJava例外によりJavaコールが終了しました

エラー メッセージには、キャッチされなかった の説明も含まれていますが、ExceptionまだORA-29532. ExceptionPL/SQLで発生したエラー・コードとエラー・メッセージの両方を指定するfrom Javaをスローする方法はありますか?

4

2 に答える 2

5

私が知っているように、Oracle は Java エラーを直接キャッチすることはできません。そして、ORA-29532 の Oracle ドキュメント ノートは、この考えを検証します。

ORA-29532: キャッチされていないJava例外によりJavaコールが終了しました: string

原因: Java 例外またはエラーが通知され、Java コードで解決できませんでした。

処置: この動作が意図されていない場合は、Javaコードを変更してください。

このテキストによると、Java コードで例外を処理する必要があると思います。

あなたはこれらのものでそれを解決することができます:

  1. Java 関数の戻り値は、void ではなく String である可能性があり、戻り変数でエラーの説明を送信できます。
  2. Java コードでエラーを Oracle テーブルに保存し、PL/SQL コードで読み取ることができます。
  3. エラーを Oracle ユーザー ダンプ ファイルに送信するだけですSystem.out.println();

編集:アダムの最終的な解決策

これは、答えに基づいて実装したおおよそのものです。

package mypackage;

public class MyClass {

    public static final int SUCCESS = 1;
    public static final int FAILURE = 0;

    /**
     * This method actually performs the business logic.
     */
    public static void doSomething(String arg1, String arg2) throws SQLException {
        // Actually do something...
    }

    /**
     * This method is called from PL/SQL.
     */
    public static int doSomething(String arg1, String arg2, int[] errorCode, String[] errorMessage) {
        try {
            doSomething(arg1, arg2);
            return success();
        } catch (SQLException e) {
            return failure(e, errorCode, errorMessage);
        }
    }

    private static int success() {
        return SUCCESS;
    }

    private static int failure(SQLException e, int[] errorCode, String[] errorMessage) {
        errorCode[0] = e.getErrorCode();
        errorMessage[0] = e.getMessage();
        return FAILURE;
    }

}

次に、PL/SQL で次のようにします。

SUCCESS CONSTANT BINARY_INTEGER := 1;
FAILURE CONSTANT BINARY_INTEGER := 0;

SUBTYPE error_code_type  IS BINARY_INTEGER;
SUBTYPE error_message_type IS VARCHAR2(1000);

PROCEDURE
  raise_error_if_failure
  (
    status        BINARY_INTEGER,
    error_code    ERROR_CODE_TYPE,
    error_message ERROR_MESSAGE_TYPE
  )
  IS
BEGIN
  IF status = FAILURE THEN
    raise_application_error(error_code, error_message);
  END IF;
END;


FUNCTION
  do_something_in_java
  (
    arg1          VARCHAR2,
    arg2          VARCHAR2,
    error_code    OUT ERROR_CODE_TYPE,
    error_message OUT ERROR_MESSAGE_TYPE
  )
  RETURN BINARY_INTEGER
    AS LANGUAGE JAVA
    NAME 'mypackage.MyClass.doSomething(java.lang.String, java.lang.String, int[], java.lang.String[]) return int';


PROCEDURE
  do_something
  (
    arg1 VARCHAR2,
    arg2 VARCHAR2
  )
IS
  error_code    ERROR_CODE_TYPE;
  error_message ERROR_MESSAGE_TYPE;
BEGIN
  raise_error_if_failure(
      do_something_in_java(arg1, arg2, error_code, error_message),
      error_code,
      error_message
    );
END;
于 2011-08-31T11:10:24.357 に答える
0

DBMS_JAVA.endsession_and_related_state()問題を解決した例外をキャプチャするために、Oracle プロシージャ内に追加しました。また、上記の Adam のソリューションにも同意します。

于 2015-06-14T04:54:30.313 に答える