Java UDF
Java UDFとは、Java言語で実装されたユーザー定義関数(User-Defined Function)のことです。Java UDF機能を利用することで、PL/SQL層からJava言語で実装されたUDFやProcedureを呼び出すことが可能になり、PLの使用シナリオをさらに拡大できます。
Java UDF関数の作成と呼び出し
操作手順は以下のとおりです:
jarパッケージのコンパイル
注意
- 以下の例は学習用です。本番環境では、mavenなどのツールを使用してJavaコードのライフサイクルを管理してください。
- 依存関係の問題を避けるため、fat jarパッケージ、つまり
with-dependenciesjarパッケージを作成することを推奨します。現在のバージョンでは、Java UDFはまずjarパッケージにコンパイルしてからOBServerにアップロードする必要があります。 以下のコードを
my_add.jarにコンパイルしてパッケージ化した後、OBServerでJava UDFを作成できます。コードは以下のとおりです:package org.example; public class MyAdd { public static int myAddImpl(int a, int b) { int c = a + b; return c; } }その後、
javacコマンドを使用してMyAdd.javaをjarパッケージにコンパイルします(JDKは事前にインストール済みである必要があります)。コマンドは以下のとおりです:mkdir -p target && javac -g -d target MyAdd.java && cd target && jar cvf my_add.jar * jarパッケージのアップロード
jarパッケージのコンパイルが完了したら、Java UDFで使用できるようにOBServerにアップロードする必要があります。OceanBaseデータベースのOracleモードでは、
DBMS_JAVA.OB_LOADJARを使用してjarパッケージをアップロードできます。jarパッケージがOBServerノード上にある場合は、utl_fileを使用してファイル内容を読み取ってからアップロードできます。jarパッケージがリモートノード上にある場合は、JDBCを使用してアップロードできます。説明
DBMS_JAVA.OB_LOADJARは2つのパラメータを受け取ります。最初のパラメータはBLOB型のjarパッケージbinaryで、2番目のパラメータはオプションのflagです。-Fを指定すると、同名のクラスに遭遇した際に既存の結果を上書きします。ローカルjarパッケージのアップロード
以下のPL/SQLを使用して、OBServerのローカルにあるjarパッケージをアップロードできます:
-- jarパッケージがあるディレクトリ CREATE OR REPLACE DIRECTORY JAR_DIR AS 'path/to/direcotry/of/jar'; -- jarパッケージの読み込みとアップロード DECLARE v_file UTL_FILE.FILE_TYPE; v_buffer RAW(32767); v_blob BLOB; v_amount BINARY_INTEGER := 32767; BEGIN DBMS_LOB.CREATETEMPORARY(v_blob, TRUE); v_file := UTL_FILE.FOPEN('JAR_DIR', 'my_add.jar', 'r'); BEGIN LOOP UTL_FILE.GET_RAW(v_file, v_buffer, v_amount); DBMS_LOB.WRITEAPPEND(v_blob, UTL_RAW_LENGTH(v_buffer), v_buffer); END LOOP; EXCEPTION WHEN NO_DATA_FOUND THEN NULL; END; UTL_FILE.FCLOSE(v_file); -- -Fは強制的にアップロードするために使用します。 DBMS_JAVA.OB_LOADJAR(v_blob, '-F'); DBMS_LOB.FREETEMPORARY(v_blob); EXCEPTION WHEN OTHERS THEN IF UTL_FILE.IS_OPEN(v_file) THEN UTL_FILE.FCLOSE(v_file); END IF; IF DBMS_LOB.ISTEMPORARY(v_blob) = 1 THEN DBMS_LOB.FREETEMPORARY(v_blob); END IF; RAISE; END; /リモートのjarパッケージをアップロードする
以下のJavaコードを使用して、JDBC経由でOBServer上のリモートjarパッケージをアップロードできます。
// url is location of the jar void ob_loadjar(String url) throws IOException, SQLException { InputStream is = new URL(url).openStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); { byte[] bytes = new byte[40960]; int len; while ((len = is.read(bytes)) != -1) { baos.write(bytes, 0, len); } } PreparedStatement ps = conn.prepareStatement( "declare\n" + "jar blob := ?;\n" + "flags varchar2(64) := ?;\n" + "begin\n" + "dbms_java.ob_loadjar(jar ,flags);\n" + "end;"); Blob b = new com.oceanbase.jdbc.Blob(baos.toByteArray()); ps.setBlob(1, b); ps.setString(2, "-F"); // -F for force ps.execute(); Statement s = conn.createStatement(); }アップロード結果を確認する
Java Classはスキーマレベルのオブジェクトであるため、アップロード後は現在のスキーマに保存されます。アップロード後は
ALL_OBJECT、DBA_OBJECTS、またはUSER_OBJECTSビューを使用して、正常にアップロードされたJava Classを確認できます。クエリ例:
obclient>select * from ALL_OBJECTS where OBJECT_TYPE = 'JAVA CLASS'; +-------+-------------------+----------------+-----------+----------------+-------------+---------------------+---------------------+---------------------+--------+-----------+-----------+-----------+-----------+--------------+---------+-------------+-------------------+-------------+-------------------+------------+---------+-----------------+---------------+---------------+----------------+----------------+ | OWNER | OBJECT_NAME | SUBOBJECT_NAME | OBJECT_ID | DATA_OBJECT_ID | OBJECT_TYPE | CREATED | LAST_DDL_TIME | TIMESTAMP | STATUS | TEMPORARY | GENERATED | SECONDARY | NAMESPACE | EDITION_NAME | SHARING | EDITIONABLE | ORACLE_MAINTAINED | APPLICATION | DEFAULT_COLLATION | DUPLICATED | SHARDED | IMPORTED_OBJECT | CREATED_APPID | CREATED_VSNID | MODIFIED_APPID | MODIFIED_VSNID | +-------+-------------------+----------------+-----------+----------------+-------------+---------------------+---------------------+---------------------+--------+-----------+-----------+-----------+-----------+--------------+---------+-------------+-------------------+-------------+-------------------+------------+---------+-----------------+---------------+---------------+----------------+----------------+ | SYS | org/example/MyAdd | NULL | 501027 | NULL | JAVA CLASS | 2026-03-24 18:03:26 | 2026-03-24 18:03:26 | 2026-03-24 18:03:26 | VALID | N | N | N | 0 | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | +-------+-------------------+----------------+-----------+----------------+-------------+---------------------+---------------------+---------------------+--------+-----------+-----------+-----------+-----------+--------------+---------+-------------+-------------------+-------------+-------------------+------------+---------+-----------------+---------------+---------------+----------------+----------------+ 1 row in set (1.195 sec) obclient>select * from DBA_OBJECTS where OBJECT_TYPE = 'JAVA CLASS'; +-------+-------------------+----------------+-----------+----------------+-------------+---------------------+---------------------+---------------------+--------+-----------+-----------+-----------+-----------+--------------+---------+-------------+-------------------+-------------+-------------------+------------+---------+-----------------+---------------+---------------+----------------+----------------+ | OWNER | OBJECT_NAME | SUBOBJECT_NAME | OBJECT_ID | DATA_OBJECT_ID | OBJECT_TYPE | CREATED | LAST_DDL_TIME | TIMESTAMP | STATUS | TEMPORARY | GENERATED | SECONDARY | NAMESPACE | EDITION_NAME | SHARING | EDITIONABLE | ORACLE_MAINTAINED | APPLICATION | DEFAULT_COLLATION | DUPLICATED | SHARDED | IMPORTED_OBJECT | CREATED_APPID | CREATED_VSNID | MODIFIED_APPID | MODIFIED_VSNID | +-------+-------------------+----------------+-----------+----------------+-------------+---------------------+---------------------+---------------------+--------+-----------+-----------+-----------+-----------+--------------+---------+-------------+-------------------+-------------+-------------------+------------+---------+-----------------+---------------+---------------+----------------+----------------+ | SYS | org/example/MyAdd | NULL | 501027 | NULL | JAVA CLASS | 2026-03-24 18:03:26 | 2026-03-24 18:03:26 | 2026-03-24 18:03:26 | VALID | N | N | N | 0 | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | +-------+-------------------+----------------+-----------+----------------+-------------+---------------------+---------------------+---------------------+--------+-----------+-----------+-----------+-----------+--------------+---------+-------------+-------------------+-------------+-------------------+------------+---------+-----------------+---------------+---------------+----------------+----------------+ 1 row in set (0.451 sec) obclient>select * from USER_OBJECTS where OBJECT_TYPE = 'JAVA CLASS'; +-------------------+----------------+-----------+----------------+-------------+---------------------+---------------------+---------------------+--------+-----------+-----------+-----------+-----------+--------------+---------+-------------+-------------------+-------------+-------------------+------------+---------+-----------------+---------------+---------------+----------------+----------------+ | OBJECT_NAME | SUBOBJECT_NAME | OBJECT_ID | DATA_OBJECT_ID | OBJECT_TYPE | CREATED | LAST_DDL_TIME | TIMESTAMP | STATUS | TEMPORARY | GENERATED | SECONDARY | NAMESPACE | EDITION_NAME | SHARING | EDITIONABLE | ORACLE_MAINTAINED | APPLICATION | DEFAULT_COLLATION | DUPLICATED | SHARDED | IMPORTED_OBJECT | CREATED_APPID | CREATED_VSNID | MODIFIED_APPID | MODIFIED_VSNID | +-------------------+----------------+-----------+----------------+-------------+---------------------+---------------------+---------------------+--------+-----------+-----------+-----------+-----------+--------------+---------+-------------+-------------------+-------------+-------------------+------------+---------+-----------------+---------------+---------------+----------------+----------------+ | org/example/MyAdd | NULL | 501027 | NULL | JAVA CLASS | 2026-03-24 18:03:26 | 2026-03-24 18:03:26 | 2026-03-24 18:03:26 | VALID | N | N | N | 0 | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | +-------------------+----------------+-----------+----------------+-------------+---------------------+---------------------+---------------------+--------+-----------+-----------+-----------+-----------+--------------+---------+-------------+-------------------+-------------+-------------------+------------+---------+-----------------+---------------+---------------+----------------+----------------+ 1 row in set (0.839 sec)PL関数を作成する
PL UDFまたはProcedureを作成する際に、
LANGUAGE JAVA句を指定することで、そのPLがJava関数/手続きのラッピングであることを示します。さらにNAME句を使用してエントリメソッドのシグネチャを指定します。例:create or replace function my_add(a number, b number) return number as LANGUAGE JAVA NAME 'org.example.MyAdd.myAddImpl(int, int) return int'; /説明
- PL関数または手続きのラッピングでは、同一スキーマ内の
Java Classのみを使用できます。 - JARパッケージのアップロードとPL/SQLパッケージの作成には厳密な順序要件はありません。PL/SQLパッケージを呼び出す際に対応するJavaクラスオブジェクトが見つかることを保証する必要があります。
JAVA UDF関数を呼び出す
注意
一部のUDFの実行時にはファイルやネットワークなどの機密権限が必要になる場合があります。そのため、事前にDBAがSYSテナントで該当するユーザー/ロールに権限を付与しておく必要があります。そうでない場合、実行時にエラーが発生します。例えば、OracleテナントのSYSユーザーに
/etc/os-releaseファイルに対するread権限を付与します。例:
説明
この例の関数には特別な権限が不要なため、権限付与の手順は省略できます。
obclient> call dbms_java.grant_permission('SYS', 'java.io.FilePermission', '/etc/os-release', 'read') tenant='oracle';権限付与後は、通常のPL UDFやProcedureと同様にJava UDFを使用できます。
obclient> select my_add(1, 2) from dual; +-------------+ | MY_ADD(1,2) | +-------------+ | 3 | +-------------+ 1 row in set (0.007 sec)
- PL関数または手続きのラッピングでは、同一スキーマ内の
使用上の制限
- OceanBaseデータベースV4.4.2 BP1バージョンでは、OBServer側でJavaソースコードからJava UDFを作成することは現在サポートされていません。
- ソースコードに
oracle.sql.BLOBが含まれる場合は、java.sql.Blobに置き換える必要があります。 - ソースコードに
oracle.sql.CLOBが含まれる場合は、java.sql.Clobに置き換える必要があります。
関連ドキュメント
DBMS_JAVA.OB_LOADJARは、Jarパッケージを外部リソースとしてOBServerにアップロードするために使用されます。このシステムパッケージの詳細については、DBMS_JAVA.OB_LOADJARを参照してください。