实现 Java 存储过程 IBM DB2 for i (AS400)

Posted

技术标签:

【中文标题】实现 Java 存储过程 IBM DB2 for i (AS400)【英文标题】:Implementing Java stored procedure IBM DB2 for i (AS400) 【发布时间】:2015-04-07 09:08:28 【问题描述】:

我创建的Java存储过程如下,能够使用AS400 Qshell命令解释器生成.class文件。

    import java.sql.*;

    public class sample 
    
        public sample()
            super();
        

        /**
         * @param args
         */
        public static void Test(int test) throws SQLException, Exception 
            // TODO Auto-generated method stub
            try
               Class.forName ("com.ibm.as400.access.AS400JDBCDriver").newInstance ();

                String url  = "jdbc:as400://ilava;naming=system;prompt=false;user=IPGUI;password=IPGUI;libraries=IPSRFILI,IPTSFILI,IPWMFILI,IPPAFILI,IPASFILI,IPSAFILI,IPTSUTL;translate binary=true";          
                Connection con = DriverManager.getConnection(url);          
                PreparedStatement ps = con.prepareStatement("INSERT INTO IPTSFILI.TEMP VALUES ('IP', 'WELCOME TO SQLJ')");
                ps.executeUpdate();
                ps.close();
                con.close();                
             
            catch (Exception e)
              
                System.out.println (e);
                System.exit(1);             
                                   
           
 

创建了相应的存储过程

CREATE procedure IPTSFILI.SPSAMPLE ( 
    IN TEST INTEGER ) 
    LANGUAGE JAVA 
    SPECIFIC IPTSFILI.SPSAMPLE 
    DETERMINISTIC 
    MODIFIES SQL DATA 
    CALLED ON NULL INPUT 
    EXTERNAL NAME 'sample!Test' 
    PARAMETER STYLE JAVA ;

当程序被调用(在 JAVA 中使用 callable 语句)时,它会给出以下错误

java.sql.SQLException: [SQL4304]  Java stored procedure or user-defined function SPSAMPLE, specific name SPSAMPLE could not load Java class Ä?_ÑÂ_À¦ÀÂÄ/øøàâàÊÑÎÁÊ for reason code 3.
    at com.ibm.as400.access.JDError.throwSQLException(JDError.java:687)
    at com.ibm.as400.access.JDError.throwSQLException(JDError.java:653)
    at com.ibm.as400.access.AS400JDBCStatement.commonExecute(AS400JDBCStatement.java:920)
    at com.ibm.as400.access.AS400JDBCPreparedStatement.execute(AS400JDBCPreparedStatement.java:1018)
    at Exec.main(Exec.java:23)

.class 文件放在QIBM\UserData\OS400\SQLLib\Function 目录中。

关于如何解决这个问题的任何建议?

【问题讨论】:

你在哪里调用存储过程?在您的代码中看不到它。此外,提供完整的堆栈跟踪会有所帮助 @Ortis,更新了堆栈跟踪。 @AntoKris 类应该实现COM.ibm.db2.app.StoredProc 接口吧?你可以试试看会发生什么 看起来像是编码问题,您是如何创建存储过程的?您可以尝试使用 iSeries 访问重新创建它吗? 【参考方案1】:

您可能没有以正确的方式指定程序。查看OS400 和Java stored proc (see Chap 7) 的文档,我认为您在这里缺少几个步骤。我建议从文档中获取代码并运行它,然后替换为您自己的实现。

【讨论】:

我按照第 7 章中提到的步骤进行操作,但仍然遇到与“ [SQL4304] Java 存储过程或用户定义函数 SPSAMPLE,特定名称 SPSAMPLE 无法加载 Java 类 Ä?_ÑÂ_À¦ ÀÂÄ/øøàâàÊÑÎÁÊ 原因代码为 3。“您能建议摆脱这种情况的方法吗? 你试过运行这个例子吗?如果有效,您可以排除编码问题。 我试过同样的教程,但是我错过了对java程序“CRTJVAPGM CLSF(Db2CusInCity.class) OPTIMIZE(40)”的优化。有必要吗?【参考方案2】:

您的 Java 代码存在一些问题。

    不应在 Java 存储过程中使用 System.out。由于系统的性质,如果在回收的 QZDASOINIT 或 QSQSRVR 作业中调用 Java 存储过程,System.out 将无法正常工作。

    您不应在通话中使用 System.exit(1)。该调用将结束 JVM,一旦 JVM 结束,就无法重新启动。

    如果要访问定义 Java 存储过程的同一系统上的表,您可能应该使用本机 JDBC 驱动程序。要获得使用本机驱动程序的 JDBC 连接,您应该调用 DriverManager.getConnection("jdbc:default:connection");

    如果您没有捕获异常,如果您使用 JDBC 客户端调用存储过程,大多数 JDBC 异常都会正确返回。

我将程序更新为如下所示。

import java.sql.*;

public class sample 

    public sample()
        super();
    

    /**
     * @param args
     */
    public static void Test(int test) throws SQLException, Exception 

           String url  = "jdbc:default:connection";
            Connection con = DriverManager.getConnection(url);          
            PreparedStatement ps = con.prepareStatement("INSERT INTO IPTSFILI.TEMP VALUES ('IP', 'WELCOME TO SQLJ')");
            ps.executeUpdate();
            ps.close();
            con.close();                
       

当我调用它时,我得到以下异常(因为我没有在我的系统上创建文件)。

SQLState: 42704
Message:  [SQL0204] TEMP in IPTSFILI type *FILE not found. 
Vendor:   -204

您还需要检查数据库服务器作业的 JOB CCSID 是否不是 65535。如果您的 JOB CCSID 是 65535,您应该收到以下错误,但我怀疑 6.1 之前的版本可能没有正确检测到这一点。

 CALL QSYS.QCMDEXC('Chgjob ccsid(65535)                ',000000020.00000)
 call SPSAMPLE(3)

 *** SQLException caught ***
 Statement was call SPSAMPLE(3)
 SQLState: 57017
 Message:  [SQL0332] Character conversion between CCSID 65535 and CCSID 1200 not valid.
 Vendor:   -332

【讨论】:

感谢您的回复。我尝试了您建议的方式,但收到错误为 SQL 状态:42724 供应商代码:-4304 消息:[SQL4304] Java 存储过程或用户定义函数 SPSAMPLE,特定名称 SPSAMPLE 无法加载 Java 类 Ä?_ÑÂ_À¦ÀÂÄ/øøàâàÊÑÎÁÊ原因码 3。 @AntoKris 您使用的是什么 IBM i 版本?您可以删除该过程并改用此创建语句吗? CREATE 过程 IPTSFILI.SPSAMPLE ( IN TEST INTEGER ) 语言 JAVA 参数样式 JAVA 确定性修改 SQL 数据调用 NULL 输入外部名称 'sample.Test' 7.1版。感谢您的回复。 收到类似消息的错误:[SQL4304] Java 存储过程或用户定义函数 MYJAVASTOREPROC,特定名称 MYJAVASTOREPROC 无法加载 Java 类 SP,原因代码为 1。1 -- 找不到该类类路径。 执行以下工作: --- 创建函数 getProperty(key varchar(200)) 返回 varchar(1024) 语言 java 参数样式 java 外部名称 'java.lang.System.getProperty' -- 然后--- select getProperty('java.home') from sysibm.sysdummy1 -- 在我的 7.1 系统上,查询返回 /QOpenSys/QIBM/ProdData/JavaVM/jdk60/32bit/jre

以上是关于实现 Java 存储过程 IBM DB2 for i (AS400)的主要内容,如果未能解决你的问题,请参考以下文章

如何在 IBM Data Studio 中查看 DB2 存储过程的解释计划?

使用 IBM DB2 Connect 驱动程序调用 i 系列上的存储过程

我们能在 AQT(Advanced Query Tool)中看到 IBM DB2 存储过程的内容吗?

通过 JMeter 调用 DB2 存储过程时出现语法错误

DB2 for IBM i:缺少 sql_function

DB2 for IBM i (iSeries) 日期 - 需要比较(当前日期 - 1)