杰瑞科技汇

Oracle如何调用Java存储过程?

整个过程的核心是 Oracle JVM (Java Virtual Machine),它内嵌在 Oracle 数据库中。

Oracle如何调用Java存储过程?-图1
(图片来源网络,侵删)

下面我将分步详细解释整个过程,从环境准备到具体调用,并附上完整的示例。


核心概念

  1. Oracle JVM: 数据库中一个完整的 Java 运行时环境,你需要先在数据库中启用它。
  2. loadjava 实用工具: 一个命令行工具,用于将 Java 类文件(.class)或 JAR 文件加载到 Oracle 数据库中,并将其存储为数据库对象。
  3. CREATE AND RESOLVE JAVA SOURCE: 也可以直接在 SQL*Plus 或其他工具中编写 Java 源代码,并让数据库编译它。
  4. CREATE JAVA: 用于加载已编译的 Java 类。
  5. CREATE OR REPLACE AND COMPILE JAVA SOURCE: 用于创建或替换 Java 源代码并编译它。
  6. CREATE PROCEDURE/FUNCTION: 这是关键一步,它创建一个数据库的存储过程或函数,并将其“映射”到一个静态的 Java 方法上,当你在 SQL 或 PL/SQL 中调用这个存储过程时,实际上是在执行 Java 方法。

详细步骤与示例

假设我们要实现一个简单的功能:在数据库中调用一个 Java 方法,该方法接收一个字符串,然后将它转换为大写并返回。

第 1 步:准备 Java 环境

确保你的 Oracle 数据库已经启用了 JVM,安装数据库时会默认安装,但可能并未启用,你可以使用以下 SQL 查询来检查:

-- 查看是否安装了 JVM
SELECT owner, object_name, object_type, status
FROM all_objects
WHERE object_type LIKE '%JAVA%' AND object_name = 'JAVAVM';

JAVAVM 对象存在且状态为 VALID,则 JVM 已安装,如果未启用,需要以 SYS 用户身份运行 dbms_java 包来设置(具体步骤请参考 Oracle 官方文档,因为这涉及到数据库安全配置)。

Oracle如何调用Java存储过程?-图2
(图片来源网络,侵删)

第 2 步:编写 Java 代码

创建一个 Java 类,它将包含我们想要调用的方法。注意

  • 方法必须是 public static 的。
  • 参数和返回值的类型必须是 Java 原始类型或 Oracle 可以自动映射的类型(如 String, java.sql.Date, java.math.BigDecimal 等)。

StringUtils.java

package com.example.utils;
public class StringUtils {
    /**
     * 将输入的字符串转换为大写
     * @param input 输入字符串
     * @return 转换后的大写字符串
     */
    public static String toUpperCase(String input) {
        if (input == null) {
            return null;
        }
        System.out.println("Java 方法被调用,输入是: " + input);
        return input.toUpperCase();
    }
    /**
     * 一个无返回值的方法,用于打印信息
     * @param message 要打印的消息
     */
    public static void printMessage(String message) {
        System.out.println("[来自 Java 的消息]: " + message);
    }
}

第 3 步:将 Java 代码加载到数据库

你有两种主要方式可以将代码加载到数据库中。

方式 A:使用 loadjava 命令行工具 (推荐用于 JAR 文件)

Oracle如何调用Java存储过程?-图3
(图片来源网络,侵删)
  1. 编译 Java 代码:

    javac -d . StringUtils.java

    这会生成 com/example/utils/StringUtils.class 文件。

  2. 打包成 JAR (可选,但推荐):

    jar -cvf StringUtils.jar com/
  3. 使用 loadjava 上传: 你需要知道你的数据库 TNS 名称(或主机、端口、SID/SERVICE_NAME)以及一个有权创建 Java 对象的用户(如 SCOTT)。

    loadjava -user scott/tiger@orcl -resolve StringUtils.jar
    • -user scott/tiger@orcl: 数据库用户名/密码@连接字符串。
    • -resolve: 加载后立即解析(编译)Java 代码,如果省略,代码只是加载,需要后续手动编译。

方式 B:使用 SQL 语句 (适合单个简单类)

直接在 SQL*Plus 或类似工具中执行:

-- 创建或替换 Java 源代码并编译
CREATE OR REPLACE AND COMPILE JAVA SOURCE NAMED 'StringUtils' AS
package com.example.utils;
public class StringUtils {
    public static String toUpperCase(String input) {
        if (input == null) {
            return null;
        }
        System.out.println("Java 方法被调用,输入是: " + input);
        return input.toUpperCase();
    }
    public static void printMessage(String message) {
        System.out.println("[来自 Java 的消息]: " + message);
    }
};
/

是执行 SQL 语句的命令。

加载完成后,你可以查询 USER_OBJECTS 来验证:

SELECT object_name, object_type, status
FROM user_objects
WHERE object_type = 'JAVA CLASS';

你应该能看到 STRINGUTILS 对象,并且状态为 VALID

第 4 步:创建 PL/SQL 包装器(调用 Java 方法)

这是最关键的一步,我们需要创建一个 PL/SQL 存储过程或函数,让它指向我们刚才加载的 Java 方法。

创建一个有返回值的函数 (映射 toUpperCase)

CREATE OR REPLACE FUNCTION java_to_uppercase(p_input IN VARCHAR2)
RETURN VARCHAR2
AS LANGUAGE JAVA
NAME 'com.example.utils.StringUtils.toUpperCase(java.lang.String) return java.lang.String';
/
  • AS LANGUAGE JAVA: 声明这是一个 Java 语言调用。
  • NAME '...': 这是 Java 方法的完整签名,格式为 '包名.类名.方法名(参数列表) return 返回类型'
  • 注意:在 SQL/PL/SQL 中,VARCHAR2 类型会自动映射到 Java 的 java.lang.String

创建一个无返回值的过程 (映射 printMessage)

CREATE OR REPLACE PROCEDURE java_print_message(p_message IN VARCHAR2)
AS LANGUAGE JAVA
NAME 'com.example.utils.StringUtils.printMessage(java.lang.String)';
/
  • 对于 PROCEDURE(过程),没有 RETURN 部分。

第 5 步:调用和测试

你可以像调用普通的 PL/SQL 过程和函数一样调用它们了。

调用函数

SET SERVEROUTPUT ON; -- 确保 PL/SQL 的输出可以显示
DECLARE
  v_result VARCHAR2(100);
BEGIN
  v_result := java_to_uppercase('Hello from Java!');
  DBMS_OUTPUT.PUT_LINE('PL/SQL 收到的结果是: ' || v_result);
END;
/

预期输出:

Java 方法被调用,输入是: Hello from Java!
PL/SQL 收到的结果是: HELLO FROM JAVA!

调用过程

BEGIN
  java_print_message('This is a test message from PL/SQL.');
END;
/

预期输出:

[来自 Java 的消息]: This is a test message from PL/SQL.

重要注意事项和最佳实践

  1. 性能:

    • 首次调用有开销: JVM 需要被“预热”,第一次调用 Java 代码会比后续调用慢。
    • 避免频繁调用: 对于非常简单的、单行的操作(如字符串拼接、简单算术),直接使用 PL/SQL 内置函数性能更高,将 Java 用于复杂的算法、数据处理或外部集成。
  2. 权限:

    • 调用 Java 存储过程的用户需要 EXECUTE 权限。
    • Java 代码需要访问文件系统、网络等,你需要使用 DBMS_JAVA 包的 GRANT_PERMISSION 方法来授予权限,允许读取文件:
      BEGIN
        DBMS_JAVA.GRANT_PERMISSION('SCOTT', 'SYS:java.io.FilePermission', '<<ALL FILES>>', 'read');
      END;
      /
  3. 错误处理:

    • Java 代码抛出异常,PL/SQL 调用会失败,你可以使用 PRAGMA EXCEPTION_INITEXCEPTION 块来捕获和处理这些错误。
    • 你可以在 Java 代码中使用 throw new SQLException("错误信息", "错误代码"); 来将 Java 异常转换为 PL/SQL 可识别的数据库错误。
  4. 调试:

    • 调试 Java 存储过程比较困难,一个常用的技巧是使用 System.out.println() 将调试信息打印到标准输出,然后在 PL/SQL 中使用 DBMS_OUTPUT.PUT_LINE 来捕获和显示这些信息。
    • 对于更复杂的调试,Oracle 提供了 jdb (Java Debugger) 的服务器模式,但这需要更复杂的配置。
  5. 部署:

    • 对于生产环境,推荐将所有相关的 Java 类打包成一个 JAR 文件,然后使用 loadjava 工具一次性部署,这样更易于管理和版本控制。

通过以上步骤,你就可以成功地在 Oracle 存储过程中调用 Java 代码,极大地扩展了数据库应用的功能和灵活性。

分享:
扫描分享到社交APP
上一篇
下一篇