# Reference:PL/Java PL/Java 是允许使用 Java™ 编程语言定义存储过程、触发器和函数的数据库扩展, OushuDB 的 PL/Java 扩展基于 Greenplum 数据库所用版本和开源的 1.5.0 版本。 本章节对 PL/Java 功能进行说明。 ## PL/Java 安装 PL/Java 提供了单独的rpm安装包,在所有数据库节点上使用 yum install 安装: ```bash lava ssh -f ~/oushuhosts -e "yum install -y oushu-plava" ``` ## PL/Java 使用 ### 创建 Extension PL/Java 扩展只能被 `CREATE EXTENSION` 命令创建和初始化 , 初始化过程需要建立元数据表及其索引, 因为 Magma 存储对索引的支持相对完善, 所以调用命令时默认表空间应当被设置为 Magma 存储上的表空间,通常可以使用 `magma_catalog`。 此时创建 Extension 的语句如下: ```sql SET default_tablespace TO magma_catalog; CREATE EXTENSION pljava; ``` ### 部署 JAR 包 用户自己编写的 Java 函数需要打包为 JAR 包,命名应符合 JDK 命名要求, 如果用到了其它依赖项,用户在打包时既可以把所有类打包在一个文件中,形成 Fat JAR, 也可以将依赖的 JAR 包和用户 JAR 包分别部署。 JAR 包被强烈建议部署在默认路径 `$GPHOME/share/postgresql/pljava/` 目录中,以便统一管理,如有需要用户可以创建子目录。 尽管不建议这么做,但在有特殊需求时,用户仍然可以选择把 JAR 包部署在任意目录下,只需要确认数据库拥有对应目录的读取权限。 所有部署的JAR包应当被复制和部署到所有节点的相同目录下,并授予数据库读取权限。 在使用对应的用户自定义函数或触发器等时,用户需要设置 GUC 值 `pljava_classpath`,包含 JAR 包或其所在的目录,多个目录用英文分号分隔, 详细说明可参考[Greenplum 的 PL/Java 语言扩展文档](https://gp-docs-cn.github.io/docs/ref_guide/extensions/pl_java.html)。 ### 使用 Extension PL/Java 提供了 `java` 和 `javau` 两种存储过程语言,可以在创建用户自定义函数时使用,更多详细用法可参考[Greenplum 的 PL/Java 语言扩展文档](https://gp-docs-cn.github.io/docs/ref_guide/extensions/pl_java.html)和[开源 PL/Java 主页](https://tada.github.io/pljava/)。 以 PL/Java 内置的一个示例函数为例, 类 `org.postgresql.pljava.example.Parameters` 的静态函数 `getTimestamp` 输入参数为空, 返回值为 `java.sql.Timestamp` 类型,将其定义为数据库中输入参数为空,返回值为 `timestamp` 类型的用户自定义函数 `java_getTimestamp`。 用 SQL 声明用户自定义函数: ```sql CREATE FUNCTION java_getTimestamp() RETURNS timestamp AS 'org.postgresql.pljava.example.Parameters.getTimestamp' LANGUAGE java; ``` 设置 `pljava_classpath` 包含对应 JAR 包路径,示例 JAR 包被部署在默认目录中,可使用相对路径( JAR 包名称中的版本号 1.5.0.1 请以实际为准): ```sql SET pljava_classpath TO 'pljava-examples-1.5.0.1.jar'; ``` 调用用户自定义函数,该函数的作用是返回当前系统时间的时间戳: ```sql SELECT java_getTimestamp(); ``` 不再需要该函数时可使用 SQL 删除: ```sql DROP FUNCTION java_getTimestamp; ``` ### 删除Extension 删除 PL/Java EXTENSION 的方法如下所示: ```sql DROP EXTENSION pljava [CASCADE]; ``` #### 注意事项 如果 EXTENSION 被其他对象依赖(如已创建的用户自定义函数),需要加入 CASCADE (级联)关键字,删除所有依赖对象。 ### 使用限制 OushuDB 的 PL/Java 扩展相比于[ Greenplum 的 PL/Java 语言扩展](https://gp-docs-cn.github.io/docs/ref_guide/extensions/pl_java.html) 有一些额外的使用限制,已知问题包括: - 在 Java 函数包含多线程代码时,新线程无法使用 PL/Java 设置的映射到 PostgreSQL SPI 函数的 JDBC 驱动程序,仅保证入口线程可正常使用所有功能; - PL/Java 定义的 `java` 和 `javau` 两种语言不再有实质性区别,用户无法依赖 `javau` 限制 Java 代码执行危险操作(如读写文件、修改 JVM 系统设置甚至关闭 JVM 等); - `pljava_vmoptions` 在大多数场景中不会生效,用户在初次使用时应当会收到提示 `INFO: Java virtual machine is already running. PL/Java will reuse it and "pljava_vmoptions" takes no effects.`,如果有修改 JVM 启动参数的需求,应修改外表相应参数 `oushu_external_jni_vmoptions` 并重启数据库; - OushuDB 使用的 Java 运行时版本为 17,用户在编译打包 JAR 包时需要注意编译目标版本,如 `javac` 命令的 `--target` 参数,低于 Java 1.8 的 JAR 包可能无法正常使用。