在 Apache Derby 中使用 Java 个函数

Use Java functions with Apache Derby

我在 Apache Derby 中使用函数时遇到过问题,因为我无法让 Derby 找到我自定义的函数。典型的错误消息如下所示:

The class 'de.uniba.kinf.projm.hylleblomst.database.sql.utils.GroupConcat' does not exist or is inaccessible. 
This can happen if the class is not public.

文档指出该方法必须是 public 并且是静态的。这就是我想要使用的:

package de.uniba.kinf.projm.hylleblomst.database.sql.utils;
public final class GroupConcat {
    public static String groupConcat(String separator, String... arguments) {
        StringBuilder result = new StringBuilder("");
        for (String arg : arguments) {
            result.append(arg + separator + " ");
        }
        result.delete(result.length() - 2, result.length());
        return result.toString();
    }
}

基本上我只想将 GroupConcat 功能添加到 Derby 标准中未提供的数据库中。我用来将函数添加到数据库的语句是这样的:

CREATE FUNCTION SQL_UTIL.GROUP_CONCAT 
    ( SEPARATOR CHAR, ARGS VARCHAR(255) ... )
    RETURNS VARCHAR(2000)
    PARAMETER STYLE DERBY
    NO SQL LANGUAGE JAVA
    EXTERNAL NAME 'de.uniba.kinf.projm.hylleblomst.database.sql.utils.GroupConcat.groupConcat'

我还将 GroupConcat class 打包到一个 jar 中,并将其添加到 Derby 应该能够找到它的 class 路径并将其直接添加到数据库中。这是我所做的: .jar 位于项目的 lib 文件夹中,它也是构建路径的一部分(我使用的是 Eclipse)。它在项目的 CLASSPATH 文件中的条目如下所示:

<classpathentry kind="lib" path="lib/groupConcat.jar"/>

出于良好的措施和一些绝望,我还将它添加到我的系统的 class 路径中:

. ; ..;%DERBY_HOME%\lib\derby.jar;%DERBY_HOME%\lib\derbytools.jar;C:\Users\workspace\kinf-workspace\General\lib

我的错误可能非常微不足道,但我对 Derby 和一般的数据库还很陌生,所以我很感激任何帮助。

提前致谢!

我不完全确定你的情况出了什么问题,但我会继续审查和检查构建过程中的 CLASSPATH 和包名称处理。

我拿了你的代码,编辑了包语句,并在一个非常简单的例子中成功地使用了它(据我所知):

C:\Users\Bryan\derby\tests\jfunc>vim GroupConcat.java
C:\Users\Bryan\derby\tests\jfunc>javac GroupConcat.java
 Directory of C:\Users\Bryan\derby\tests\jfunc
07/11/2015  08:53 AM               832 GroupConcat.class
07/11/2015  08:53 AM               440 GroupConcat.java
C:\Users\Bryan\derby\tests\jfunc>java -cp \users\bryan\derby\trunk\jars\sane\derbyrun.jar;. org.apache.derby.tools.ij
ij version 10.12
ij> connect 'jdbc:derby:brydb;create=true';
ij> CREATE FUNCTION SQL_UTIL.GROUP_CONCAT
    ( SEPARATOR CHAR, ARGS VARCHAR(255) ... )
    RETURNS VARCHAR(2000)
    PARAMETER STYLE DERBY
    NO SQL LANGUAGE JAVA
> > > > >     EXTERNAL NAME 'GroupConcat.groupConcat';
0 rows inserted/updated/deleted
ij> create table t1 (a int, b int);
0 rows inserted/updated/deleted
ij> insert into t1 values (1, 2);
1 row inserted/updated/deleted
ij> select sql_util.group_concat(a,b) from t1;
ERROR 42821: Columns of type 'CHAR' cannot hold values of type 'INTEGER'.
ij> create table t2 (a varchar(10), b varchar(10));
0 rows inserted/updated/deleted
ij> insert into t2 values ('a', 'b');
1 row inserted/updated/deleted
ij> select sql_util.group_concat(a,b) from t2;
1

-------------------------------------------- ----------------------------------

b


1 row selected

现在,我希望您可能希望看到 'ab' 作为结果,但我相信这是一个不同的问题,可能是因为我没有传递 'separator' 的值当我 运行 你的功能时。

可能,运行 您的程序

java -verbose:class

将帮助您确定 Derby 是否只是在错误的地方寻找您的 class。 (像 MSDN 的 ProcessMonitor 这样的工具也可能对此有用)

祝你好运,让我们知道你发现了什么!

事实证明,这个问题更具体到 Eclipse,本质上是微不足道的。虽然包含 Java-class 的 jar 已经在 class 路径中,但 Eclipse 没有将 jar 添加到 运行 配置中。显然,class 路径从那里传递到 Derby,当然它找不到 class。所以所有要做的就是将包含相关方法的 class 打包到一个 jar 中,将其添加到项目的库中,将其添加到 运行 配置的 class 路径和 运行它。

经验教训:永远不要相信你的 IDE 会完成你的(所有)工作。