跳转到主内容
新派编程网 - 新潮编程理念,全新技术课堂!

如何使用Java存储过程_在Oracle数据库内部署并执行Java代码的Loadjava工具

loadjava不能部署任意Java类,仅支持编译后的.class/.jar/.sql文件,且须满足Oracle JVM限制:禁用反射、系统类、静态初始化块(非常量)、外部JAR依赖;需用javac -target 1.8编译,类为public、无main、方法static;调试用DBMS_OUTPUT.PUT_LINE;调用需CREATE FUNCTION/PROCEDURE发布,参数用全限定名;权限需GRANT JAVAUSERPRIV等;性能差因解释执行与上下文切换,适用场景限加密、正则等Java专属功能。 loadjava 工具到底能不能直接部署任意 Java 类 不能,
loadjava
只接受已编译的
.class
文件(或
.jar
、
.sql
),且类必须满足 oracle jvm 的严格限制:不能使用反射、不能调用系统类(如
java.io.file
)、不能有静态初始化块(除非是常量赋值)、不能依赖外部 jar(除非也用
loadjava
加载进数据库)。 常见错误现象:
ORA-29534: referenced object SYS.abc could not be resolved
,往往是因为依赖的类没加载,或包名/类名大小写不匹配(Oracle 默认转大写,但类文件实际是区分大小写的)。 先用
javac -target 1.8 -source 1.8
编译(Oracle 12c+ 支持 Java 8 字节码,但不支持 9+) 确保类是
public
、无
main
方法、所有方法为
static
(存储过程入口必须是 static) 避免使用
System.out.println
—— 输出会被丢弃,调试靠
DBMS_OUTPUT.PUT_LINE
如何让 Java 方法被 SQL 或 PL/SQL 调用 必须通过
CREATE FUNCTION
或
CREATE PROCEDURE
显式发布,且签名要和 Java 方法完全对应(参数类型映射有限制)。 例如 Java 方法:
public static String greet(String name) { return "Hello, " + name; }
,对应的 SQL 发布语句是:
CREATE OR REPLACE FUNCTION greet_java(p_name VARCHAR2) RETURN VARCHAR2 AS LANGUAGE JAVA NAME 'MyClass.greet(java.lang.String) return java.lang.String';
关键点: 立即学习 “ Java免费学习笔记(深入) ”; Java 参数类型必须用全限定名(
java.lang.String
,不是
String
) Oracle 的
VARCHAR2
映射到
java.lang.String
,
NUMBER
映射到
java.math.BigDecimal
(不是
int
或
double
) 如果 Java 方法抛异常,会转成
ORA-29532: Java call terminated by uncaught Java exception
,建议在 Java 层捕获并返回错误码或空值 权限不足时 loadjava 报错的典型表现 最常见的是
ORA-29532: Java call terminated by uncaught Java exception
或
ORA-29540: class does not exist
,背后其实是权限问题,而非类不存在。 必须显式授予以下权限(由 DBA 执行):
GRANT JAVAUSERPRIV TO your_user;
(基础 Java 运行权限)
GRANT JAVASYSPRIV TO your_user;
(仅当需要访问系统类或动态类加载时才需,一般不用) 若 Java 类访问数据库(比如用
DriverManager.getConnection("jdbc:default:connection:")
),还需
GRANT SELECT_CATALOG_ROLE TO your_user;
注意:
loadjava
命令本身不检查权限是否足够,它只负责把字节码存进数据字典;真正校验权限是在首次调用时 —— 所以“加载成功但调用失败”是高频坑。 Java 存储过程性能差的几个硬伤 Oracle JVM 是解释执行的(12c 后部分支持 JIT,但默认关闭),且每次调用都涉及 SQL→Java→SQL 的上下文切换,比纯 PL/SQL 慢一个数量级是常态。 避免在循环里频繁调用 Java 函数;尽量把逻辑批量封装进单次 Java 调用 不要用 Java 做简单字符串处理(比如
UPPER
、
REPLACE
)—— PL/SQL 内置函数快得多 Java 类一旦加载,就常驻 Shared Pool,但修改后必须先
dropjava
再重新
loadjava
,否则旧版本仍在运行(没有热替换) 真正适合 Java 存储过程的场景其实很窄:需要调用外部算法库(如加密、正则、PDF 解析)、已有成熟 Java 工具类且无法重写为 PL/SQL、或与 Java EE 应用共享核心逻辑。

相关文章