0

运行调用我已加载的 JAR 文件的函数时,我在 Postgres 中收到 java.lang.ClassNotFoundException: 错误。我已经在我的数据库中安装并配置了 PL/JAVA(包括提供的示例),并且可以成功运行示例。我没有尝试加载/安装我的第一个 JAR,但我做错了。

我的主机控制操作系统版本:CentOS 6.8。Postgres 是 8.4 版。

我正在尝试安装我自己的非常简单的 java 类,它是提供的示例 Parameters.addOne 类的派生类。我所有的代码都在 /tmp 中。以下是我遵循的步骤:

道格.java:

    package com.msmetric;
    import java.math.BigDecimal;
    import java.sql.Date;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Time;
    import java.sql.Timestamp;
    import java.text.DateFormat;
    import java.text.SimpleDateFormat;
    import java.util.TimeZone;
    import java.util.logging.Logger;

    public class Doug {
      public static int addOne(int value) {
        return value + 1;
       }
    }
  1. 使用 'javac Doug.java' 编译 Doug.java 成功。

  2. 使用 'jar -cvf Doug.jar Doug.class 创建包含 Doug.class 文件的 JAR 文件。这工作正常。

现在我将 JAR 文件加载到 Postgres(公共模式)中,更改类路径,创建调用 JAR 的函数,然后尝试在 psql 提示符下运行。

  1. 从 psql 运行 sqlj.install_jar:

    select sqlj.install_jar('file:/tmp/Doug.jar','Doug',false);
    
  2. 在 Postgres 中设置类路径(来自 psql 提示 postgres=#):

    select sqlj.set_classpath('public','Doug');
    
  3. 创建调用 JAR 的函数。这个创建函数代码直接取自 PL/JAVA 附带的 examples.ddr 文件。我只是将 org.postgres 更改为 com.msmetric。

    create or replace function addone(int) returns int as 'com.msmetric.Doug.addOne(java.lang.Integer)' language java;
    

现在加载了 JAR 并创建了函数,我尝试运行它。这个函数应该简单地将 1 加到提供的数字上。

    select addone(3);

结果:错误:java.lang.ClassNotFoundException:com.msmetric.Doug

想法?

4

1 回答 1

0

很抱歉没有早点看到你的问题。在所有奇特的细节(PostgreSQL、PL/Java、模式、类路径...)之下,这里只是一些基本的 Java:如果一个 jar 文件Doug.class在 package中包含一个类com.msmetric,它在 jar 中的路径必须反映这一点: 必须的com/msmetric/Doug.class。否则,将找不到。

您可以逐步设置整个结构:

javac Doug.java mkdir com mkdir com/msmetric mv Doug.class com/msmetric/ jar -cvf Doug.jar com/msmetric/Doug.class

或者,您可以让javac自己做更多的工作:

mkdir classes javac -d classes Doug.java jar -cvf Doug.jar -C classes .

当你提供javac一个-d目录选项时,而不是仅仅在它们的源代码旁边编写类文件.java,它会将它们全部放在你命名的目录下的适当位置,然后你可以告诉jar更改到该目录并将它们全部吞下(不要忽略该命令.末尾的jar)。

一旦你解决了这个问题,如果你重试原来的步骤,你会看到你现在得到一个不同的错误:

ERROR:  Unable to find static method com.msmetric.Doug.addOne with signature (Ljava/lang/Integer;)I

Doug.java发生这种情况是因为您在with中声明了该函数int addOne(int value)(即采用原始int参数),但您在 SQL 中声明它时采用returns int as 'com.msmetric.Doug.addOne(java.lang.Integer)'了一个Integer对象。

一旦你更正了:

create or replace function addone(int) returns int as 'com.msmetric.Doug.addOne(int)' language java;

您将能够看到:

# select addone(3);
 addone 
--------
      4
(1 row)

如果您碰巧看到这个迟来的答案,请问您使用的是哪个版本的 PL/Java?这是你没有提到的一个细节。如果它早于 1.5.0,则有更新的功能可以帮助您。一方面,您可以只注释该函数:

@Function
public static int addOne(int value) {
  return value + 1;
}

并且不仅javac吐出Doug.class文件,而且吐出pljava.ddr已经正确编写 SQL 函数声明的文件(不要混淆参数类型!)。有一种方法可以将该.ddr文件包含到您创建的 jar 中,这样您就可以sqlj.install_jar使用最后一个参数进行调用,true以便它运行中的命令.ddr并且您的函数可以使用。文档中有一个 Hello, world 示例,它显示了更多它是如何完成的。

干杯,
-Chap

于 2017-05-13T06:02:02.227 回答