【发布时间】:2021-09-13 07:50:06
【问题描述】:
我创建了一个 Java 类,在 Java 中实现了 Levenshtein 距离算法,以便在 DB2 UDF 中使用它。
显然,在DB2下,注册java UDF有两种方式,一种是复制QIBM/UserData/OS400/SQLLib/Function下的.class文件,另一种是复制一个JAR,然后使用SQLJ.INSTALL_JAR。
现在,我的 Java 源代码如下所示:
package FUNCTIONS;
public class LEVENSHTEIN {
public static int levenshteinDistance (String lhs, String rhs) {
int len0 = lhs.length() + 1;
int len1 = rhs.length() + 1;
// the array of distances
int[] cost = new int[len0];
int[] newcost = new int[len0];
// initial cost of skipping prefix in String s0
for (int i = 0; i < len0; i++) cost[i] = i;
// dynamically computing the array of distances
// transformation cost for each letter in s1
for (int j = 1; j < len1; j++) {
// initial cost of skipping prefix in String s1
newcost[0] = j;
// transformation cost for each letter in s0
for(int i = 1; i < len0; i++) {
// matching current letters in both strings
int match = (lhs.charAt(i - 1) == rhs.charAt(j - 1)) ? 0 : 1;
// computing cost for each transformation
int cost_replace = cost[i - 1] + match;
int cost_insert = cost[i] + 1;
int cost_delete = newcost[i - 1] + 1;
// keep minimum cost
newcost[i] = Math.min(Math.min(cost_insert, cost_delete), cost_replace);
}
// swap cost/newcost arrays
int[] swap = cost; cost = newcost; newcost = swap;
}
// the distance is the cost for transforming all letters in both strings
return cost[len0 - 1];
}
}
在我读过的最新文档中,它说它必须尊重包结构,所以我复制了 QIBM/UserData/OS400/SQLLib/Function/FUNCTIONS 下的 LEVENSHTEIN.class。也尝试在Function下复制它,以防我误解。
还创建了一个 JAR 并像这样注册它
CALL SQLJ.INSTALL_JAR('file:/QIBM/UserData/OS400/SQLLib/Function/testMain.jar','JARFUNCTIONS',0);
我尝试注册 UDF 的方式:
CREATE OR REPLACE FUNCTION DEBUG.LV(
LHS VARCHAR(255) ,
RHS VARCHAR(255) )
RETURNS INTEGER
LANGUAGE JAVA
SPECIFIC DEBUG.LV
NOT DETERMINISTIC
READS SQL DATA
CALLED ON NULL INPUT
EXTERNAL NAME 'JARFUNCTIONS:FUNCTIONS.LEVENSHTEIN.levenshteinDistance'
PARAMETER STYLE JAVA ;
CREATE OR REPLACE FUNCTION DEBUG.LEVENSHTEIN(
LHS VARCHAR(255) ,
RHS VARCHAR(255) )
RETURNS INTEGER
LANGUAGE JAVA
SPECIFIC DEBUG.LEVENSHTEIN
NOT DETERMINISTIC
READS SQL DATA
CALLED ON NULL INPUT
EXTERNAL NAME 'FUNCTIONS.LEVENSHTEIN.levenshteinDistance'
PARAMETER STYLE JAVA ;
CREATE OR REPLACE FUNCTION DEBUG.LEVENSHTEIN(
LHS VARCHAR(255) ,
RHS VARCHAR(255) )
RETURNS INTEGER
LANGUAGE JAVA
SPECIFIC DEBUG.LEVENSHTEIN
NOT DETERMINISTIC
READS SQL DATA
CALLED ON NULL INPUT
EXTERNAL NAME 'LEVENSHTEIN.levenshteinDistance'
PARAMETER STYLE JAVA ;
所有这些都告诉我它在类路径下找不到类,并确保 .class 编译文件在 /QIBM/UserData/OS400/SQLLib/Function 下,并且它实现了必要的接口并且是公开。
根据我的阅读,使用 JAVA 样式参数,我不必扩展 UDF。另外,我的 db2_classes 中的 UDF 是一个类而不是一个接口,所以我必须扩展它而不是实现它。也试过这样做,没有任何变化。
也看到了这种声明风格,所以也尝试了这个:
CREATE OR REPLACE FUNCTION DEBUG.LEVENSHTEIN(
LHS VARCHAR(255) ,
RHS VARCHAR(255) )
RETURNS INTEGER
LANGUAGE JAVA
SPECIFIC DEBUG.LEVENSHTEIN
NOT DETERMINISTIC
READS SQL DATA
CALLED ON NULL INPUT
EXTERNAL NAME 'LEVENSHTEIN!levenshteinDistance'
PARAMETER STYLE JAVA ;
这个告诉我,名称 LEVENSHTEIN 无法从外部名称 LEVENSHTEIN!levenshteinDistance 中识别出来,并且外部名称必须是 package.subpackage.class.method
我在数据库的安全管理员下,理论上我可以创建文件和文件夹(我在 /Function 下创建了一个文件夹,它确实被创建了)
我浏览了十几本红皮书和参考资料,尝试了不同的东西,以至于我什至不记得我尝试过的所有东西。
非常感谢任何帮助。 谢谢
稍后编辑:还尝试使用空构造函数,还扩展 UDF 并使用调用 super() 的构造函数。到目前为止,没有运气
【问题讨论】:
-
您在各个步骤中遇到哪些错误?
-
@ThorbjørnRavnAndersen 我发布的那些,在复制和声明 UDF 时都没有错误。唯一的错误是在调用 UDF 时出现“未在类路径中找到”或“无法识别”
-
你在
select * from sysibm.SYSJARCONTENTS where JAR_ID = 'JARFUNCTIONS'找到你的班级吗? -
@nfgl 我知道,我可以在那里看到 FUNCTIONS.LEVENSHTEIN,但是在它说类源的地方我得到了一个“-”。不知道这样好不好。
-
这只是意味着
NULL,我让你的函数在这里工作,并且得到了NULL。您是否尝试使用select java_home from qsys2.JVM_INFO ji where job_name = QSYS2.job_name指示的 JRE 从 SQL 外部的可调用类中使用该方法?
标签: java db2 classpath user-defined-functions