SQL4306N Java存储过程或用户定义的函数无法调用Java方法

时间:2017-07-20 12:14:04

标签: java db2 java-stored-procedures

我们刚刚从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语句。它宣称的论点 list可能与数据库期望的不匹配,或者可能不是 "公共"实例方法。

用户回复:

确保使用" 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;

1 个答案:

答案 0 :(得分:0)

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

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

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

话虽如此,我真的不明白为什么你使用这种复杂的方法来检索SQL序列值。