【问题标题】:SQL4306N Java stored procedure or user-defined function could not call Java methodSQL4306N Java 存储过程或用户定义函数无法调用 Java 方法
【发布时间】:2017-12-26 03:09:42
【问题描述】:

我们刚刚从 9.5 升级到 DB2 10.5,这个过程运行良好,直到在服务器上执行升级。当我从 linux 服务器运行 jar 文件时,出现以下错误,但是当我在 windows 计算机上从 eclipse 运行完全相同的代码时,它工作得很好!如果我从 DB2 控制中心调用这个 sp,我也会收到类似的错误。我想知道是什么原因造成的,我该如何解决这个错误?

SQL4306N Java 存储过程或用户定义函数“ESADBM.GETNEXTID”, 特定名称“WHDBRMM_UTILS”无法调用 Java 方法“GetNextID”, 签名“(Ljava/lang/String;[I)V”。 SQLSTATE=42724

解释:

由 CREATE PROCEDURE 的 EXTERNAL NAME 子句给出的 Java 方法 或找不到 CREATE FUNCTION 语句。它声明的论点 列表可能与数据库期望的不匹配,或者它可能不是 “公共”实例方法。

用户回复:

确保存在带有“public”标志的 Java 实例方法,并且 此调用的预期参数列表。

sqlcode:-4306

sqlstate: 42724.

代码如下:

    package pkgUtil_v4_0_0_0;

    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    import org.hibernate.exception.JDBCConnectionException;


    public class DBSequence {
      public static final String SEQ_CONTACTID        = "ContactIDSeq"; 
      public static final String SEQ_PROJECTID        = "ProjectIDSeq";
      public static final String SEQ_LOCATIONID       = "LocationIDSeq";
      public static final String SEQ_SOURCEID         = "SourceIDSeq";
      public static final String SEQ_SURVEYID         = "SurveyIDSeq";
      public static final String SEQ_LOGICALSURVEYID  = "WageAreaIDSeq";
      public static final String SEQ_WAGEDETAILID     = "WageDetailIDSeq";
      public static final String SEQ_ORGID            = "OrgIDSeq";
      public static final String SEQ_OFFICEID         = "RegionNumberSeq";
      public static final String SEQ_LETTERID         = "LetterIDSeq";
      public static final String SEQ_DODGEID          = "DodgeIDSeq";
      public static final String SEQ_CRAFTID          = "CraftIDSeq";
      public static final String SEQ_CRAFTTITLEID     = "CraftTitleIDSeq";
      public static final String SEQ_ANALYSTID        = "AnalystIDSeq";
      public static final String SEQ_LETTERTEMPLATEID = "LetterTemplateIDSeq";
      public static final String SEQ_RECRATESID       = "RecRatesIDSeq";
      public static final String SEQ_BRIDGESCDID      = "BridgeSCDIDSeq";


      public static String drvr = "";
      public static Connection con = null;

      // utility function
      public static int getNextId(Connection lcon, String sequence) throws         SQLException {
        Boolean bFlag;
        PreparedStatement stmt = null;
        int id = 0;

        String sql = "select next value for esadbm." +
             sequence + " from SYSIBM.sysdummy1";
    //    System.out.println("String = "+sequence);
        stmt = lcon.prepareStatement(sql);
        ResultSet resultSet = stmt.executeQuery();
        if (resultSet.next()) {
          id = resultSet.getInt(1); 
        }
        resultSet.close();
        stmt.close();

        return id;
      }

      // Stored Procedure Entry Point
      public static void getNextId(String sequence, int[] seq) throws SQLException, Exception {
  System.out.println("String = "+sequence);
  System.out.println("Array = "+seq);
        if (drvr.length() == 0) {
          drvr = "jdbc:default:connection";
          con = DriverManager.getConnection(drvr);
        }
        drvr = "";
        seq[0] = getNextId(con, sequence);
        con.close();
      }

      // test procedure 
      public static void main(String args[])throws SQLException, Exception {

        try {
          System.out.println("Connecting to DB " + args[0]);

          Class.forName("com.ibm.db2.jcc.DB2Driver");
          drvr = "jdbc:db2:" + args[0];
    //      System.out.println(drvr+args[1] + args[2]);
          con = DriverManager.getConnection("jdbc:db2:" + args[0], args[1],args[2]);
    //      System.out.println(con);
            System.out.println("DB Connection Successful");
          con = DriverManager.getConnection(drvr, args[1], args[2]);

          Statement st = con.createStatement();
          String query = "set schema = 'ESADBM'";
          st.execute(query);

          System.out.println("Getting ID");

          int id = getNextId(con, SEQ_SOURCEID);

          System.out.println("Returned : " + Integer.toString(id));
        }
        catch (ClassNotFoundException cnfe) {
          cnfe.printStackTrace();
        }
        catch (SQLException sqle) {
          sqle.printStackTrace();
        }    
        catch (JDBCConnectionException e) {
            System.out.println("Unable to connect to database");
            e.printStackTrace();
        }
      }
    }

这是存储过程:

               CREATE PROCEDURE "ESADBM  "."GETNEXTID" 
                                    ( 
                            IN      SEQUENCE   CHARACTER(40),
                            OUT     ID   INTEGER
                            )
                                    DYNAMIC RESULT SETS 0 
                                    SPECIFIC WHDBRA_UTILS 
                                    EXTERNAL NAME 'pkgUtil_v4_0_0_0.DBSequence!getNextId()' 
                                    LANGUAGE JAVA     
                                    PARAMETER STYLE JAVA     
                                    NOT DETERMINISTIC 
                                    FENCED THREADSAFE 
                                    MODIFIES SQL DATA 
                                    NO DBINFO;

【问题讨论】:

  • 不确定“从 linux 服务器运行 [ning] jar 文件”是什么意思,但您需要确保正确安装了包含外部存储过程使用的类的 JAR 文件在服务器上。那么,您执行了哪些步骤来安装它?您的 Java 和 SP 代码在这里完全无关紧要。
  • 我们在 linux 服务器上执行 jar 文件。我没有对服务器上的现有设置进行任何修改,因为以前的构建在 DB2 9.5 上工作得很好,只是在升级到 DB2 10.5 后才停止工作。这有意义吗?我一直在研究如何解决这个问题,但到目前为止没有成功。与存储过程相比,方法中传递的参数类型似乎不匹配,或者与类路径有关?
  • Mustaccio,如果您对此了解更多,可以打个电话吗?我在美国东部标准时间。
  • 当然,我收取 90 美元/小时的远程咨询费用。我在哪里发送合同?

标签: java db2 java-stored-procedures


【解决方案1】:

外部例程的库(包括 Java 类和 Java 例程的 JAR 文件)必须存在于 DB2 实例目录中的特定位置。当您升级 DB2 版本时,会创建一个新实例,但不会自动复制这些库(顺便说一句,这很有意义,因为它们很有可能需要重建)。

错误消息表明实例找不到实现GETNEXTID 的Java 类文件——即DBSequence.class。需要将该类复制到数据库服务器上 DB2 10.5 实例主目录中的sqllib/function 目录,如explained in the manual。您可能还需要在sqllib/function 下创建pkgUtil_v4_0_0_0 以获得正确的包结构。确保使用与 DB2 实例运行程序所用的相同 JDK 版本来编译 Java 源代码。

完成此操作后,在您选择的 DB2 客户端中执行 CALL SQLJ.REFRESH_CLASSES() 以确保 DB2 重新加载最新版本。之后,您的存储过程应该可以正常工作。

话虽如此,我真的不明白您为什么要使用如此复杂的方式来检索 SQL 序列值。

【讨论】:

  • 那么,错误信息的哪一部分似乎不清楚?作为一个 Java 极客,您可能知道 Java 标识符是区分大小写的,不是吗。
  • 嗯,它现在不工作,错误消息告诉你原因。但是,如果您没有理由相信它,那么我只能祝您好运。
  • 我正在尝试,会及时通知您!
  • 太棒了。您需要更多帮助来解释错误消息吗?检查堆栈跟踪的管理员通知日志,然后检查 DB2 手册以了解 SQLCODE=-204 的含义,然后修复您的代码,就像您所说的极客一样。
  • Mustaccio - 非常感谢您上周的帮助!事实证明,DBA 最初使用错误的情况调用 SP,然后没有使用正确的输入参数调用存储过程,否则这一切都不是问题!我同意你所说的一切,作为我现在公司的新人,我想与其他人再次确认我没有疯!再次感谢您的帮助,希望有一天我能回报!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-01-09
  • 2011-12-05
  • 2016-12-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多