【问题标题】:Raising errors from Java stored procedures without "ORA-29532 Java call terminated by uncaught Java exception"在没有“ORA-29532 Java 调用因未捕获的 Java 异常而终止”的情况下从 Java 存储过程引发错误
【发布时间】:2011-11-07 10:34:42
【问题描述】:

假设您有一个 Java 类,它定义了一个 copyFile(String, String) 方法:

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 存储过程并抛出 Java IOException

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

在 PL/SQL 块中,引发的错误是:

ORA-29532 Java 调用被未捕获的 Java 异常终止

错误消息还包含未捕获的Exception 的描述,但它仍然是ORA-29532。有没有办法从 Java 中抛出一个 Exception 来指示错误代码和在 PL/SQL 中引发的错误消息?

【问题讨论】:

    标签: java oracle stored-procedures plsql ora-29532


    【解决方案1】:

    据我所知,Oracle 无法直接捕获 Java 错误。 ORA-29532 的 Oracle 文档说明验证了这个想法:

    ORA-29532:Java 调用被未捕获的 Java 异常终止:字符串

    原因:发出 Java 异常或错误信号,Java 代码无法解决。

    操作:修改 Java 代码,如果此行为不是预期的。

    根据本文,我认为你应该在Java代码中处理异常。

    你可以用这些东西来解决这个问题:

    1. Java 函数的返回值可能是 String - 不是 void,您可以在返回变量中发送错误描述。
    2. 您可以在 Java 代码中将错误保存到 Oracle 表中,然后在 PL/SQL 代码中读取。
    3. 您只需将错误发送到带有System.out.println(); 的Oracle 用户转储文件。

    编辑:亚当的最终解决方案

    这大致是我根据答案实现的:

    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;
    

    【讨论】:

      【解决方案2】:

      我们在 oracle 过程中添加了DBMS_JAVA.endsession_and_related_state() 来捕获异常,从而解决了这个问题。 也同意上面的亚当解决方案。

      【讨论】:

        猜你喜欢
        • 2013-04-27
        • 2019-07-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多