【问题标题】:How can I insert additional libraries to my jdbc/DB2 connection?如何将其他库插入我的 jdbc/DB2 连接?
【发布时间】:2015-03-06 20:40:59
【问题描述】:

我正在编写一个小的 java 程序,通过 jdbc(db2jcc.jar 版本 1.0.581)将数据写入 AS/400 DB2 表中,并且触发器与 INSERT 操作相关联。此触发器适用于与包含我的表 (f4104) 的库 (jdta73p10) 不同的库关联的各种表。

遵循我用来建立连接和读取完美运行的数据的代码。

import java.sql.*;
import com.ibm.db2.jcc.*;

public class ProvaNUMEAN13 {

public static void main(String[] args) throws SQLException, ClassNotFoundException {

    DB2DataSource dbds = new DB2DataSource();

    dbds.setDriverType(4);
    dbds.setServerName("a60d45bb");
    dbds.setPortNumber(446);
    dbds.setDatabaseName("prodgrp");
    dbds.setDescription("Prova collegamento");
    dbds.setUser("XXXXX");
    dbds.setPassword("XXXXX");

    Connection con = dbds.getConnection();

    Statement stmtNum = con.createStatement();
    stmtNum.executeQuery("select * from INTERFACCE.NUMEAN13");
    ResultSet rs = stmtNum.getResultSet();

    rs.next();  
    System.out.println("Valore numeratore: " + rs.getString("E13EAN"));
    System.out.println("Tipo numeratore: " + rs.getString("K13KEY"));

    stmtNum.close();

    Statement stmtAnag = con.createStatement();
    stmtAnag.executeQuery("select * from jdta73p10.f4101lb where IMLITM = " + "'" + args[0] + "'");
    ResultSet rsAna = stmtAnag.getResultSet();
    int idCodice = 0;
    if (!rsAna.next()) {

        System.out.println("Il codice " + args[0] + " non esiste in anagrafica!");

    } else {

        idCodice = rsAna.getInt("IMITM");
        System.out.println("idCodice per " + args[0] + ": " + Integer.toString(idCodice));
        Statement stmtQEAN = con.createStatement();
        stmtQEAN.executeQuery("select IVALN, IVCITM, IVLITM, IVDSC1 from jdta73p10.f4104 where IVXRT = 'B ' and IVALN = '8000000000000'");
        ResultSet rsQEAN = stmtQEAN.getResultSet();

        if (rsQEAN.next()) {
            System.out.println("Codice EAN per " + args[0] + " già presente: " + rsQEAN.getString("IVALN"));
            System.out.println("Valore EAN13: " + rsQEAN.getString("IVCITM"));
            System.out.println("Risultato ricerca per EAN13: " + rsQEAN.getString("IVLITM")+" - "+rsQEAN.getString("IVDSC1"));

        }
    }
}
}

问题是当我尝试执行 INSERT 操作时(如下所示);由于触发器执行,在 AS/400 中生成错误。

stmtQEAN.execute("insert into jdta73p10.f4104 (IVXRT,IVITM,IVCITM,IVDSC1,IVALN,IVLITM) values ('B ','18539','8000000000000','Prodotto PROVA','8000000000000','ABABABAB')");

这是 AS/400 方面的错误:

消息 ID 。 . . . . . : RNQ0211 严重性。 . . . . . . : 99

消息类型。 . . . . : 查询

发送日期。 . . . . . : 08/01/15 发送时间。 . . . . . : 10:01:31

消息。 . . . : 调用程序或过程时发生错误 *LIBL/PRHWRAPUSE (C G D F)。 原因 。 . . . . : 程序 INTERFACCE/TRG_F4104A 中的 RPG 程序 TRG_F4104A 在 语句 152 试图调用程序或过程 *LIBL/WS_MATERI,但是 无法访问程序或过程、库或所需的 服务程序。如果名称是 *N,则调用是过程绑定调用 指针。

恢复。 . . :查看作业日志以获取有关导致错误的原因的更多信息 错误并联系负责程序维护的人员。 回复消息的可能选择。 . . . . . . . . . . . . . . :

D -- 获取 RPG 格式的转储。

S -- 获取系统转储。

我的问题是:如何指定触发需要的其他库?在旧版本的工具(用 Delphi 编写)中,我使用了 Client/Access ODBC,其中有一个特殊字段,您可以在其中输入其他库,但现在我不知道该怎么做。

【问题讨论】:

  • 您应该包含确切的错误代码和消息。
  • 好的,问题已编辑并添加错误。
  • 我不认为在客户端您无能为力。触发器代码不正确或它试图调用的程序,触发器无法访问 WS_MATERI。

标签: jdbc db2 ibm-midrange


【解决方案1】:

几个解决方案。

快速实时修复 将触发器程序复制到 QGPL(临时修复。需要尽快实施永久修复

更改用于连接到 AS400 的用户配置文件的 JOBD,使其具有正确的列表。用于 JDBC 的用户配置文件应该已经被锁定,或者它是组中用户的 jdbc,所以这是一个简单的 CHGJOBD JOBD(x) LIBL(xxx xxx xxx xxx) 但必须回收连接。

更改触发器程序,使其具有硬编码库。我敢打赌你需要对文件的独占访问权。我没有工作(无法访问 iseries),所以我无法验证此解决方案。

我建议不要更改连接字符串。您最终将不得不为每台连接到数据库的机器更改它。

【讨论】:

    【解决方案2】:

    AS400 (iSeries) 允许在 jdbc url 中使用逗号分隔的库列表:

    jdbc:as400://someserver;naming=system;libraries=devfiles,prodfiles,sysibm,etc

    naming=system 表示 sql 将使用库列表。例如:

    select * from NUMEAN13
    

    naming=sql 表示 sql 将在表引用中包含库名前缀。例如:

    select * from INTERFACCE.NUMEAN13
    

    我的经验是你不能混合它们。如果您使用库列表 (naming=system),则所有 sql 不得包含库名称。如果您使用非库列表 (naming=sql),则所有 sql 必须包含库名称。

    【讨论】:

      【解决方案3】:

      感谢您的提示。

      我也在考虑使用存储过程(如您所建议的那样),但最后我发现使用另一个 IBM 包 jt400.jar 可以使用 DataSource 类,该类具有设置 AS/400 列表的方法您需要使用的库。

      下面是我如何使用 setLibraries 方法修改我的代码(现在可以使用了!)。

          import com.ibm.as400.access.*;
      
          ...
      
          AS400JDBCDataSource dbds = new AS400JDBCDataSource();
      
          dbds.setServerName("a60d45bb");
      //  dbds.setPortNumber(446);
          dbds.setDatabaseName("prodgrp");
          dbds.setDescription("Prova collegamento a numeratore EAN13");
          dbds.setUser("XXXXX");
          dbds.setPassword("XXXXX");
          dbds.setLibraries("JCOM73P10 JDTA73P10 KLDADBFER KLDADBGAM INTERFACCE SAP");
      
      
          Connection con = dbds.getConnection();
      

      这个类没有 setPort 方法,但是如果你使用标准端口(比如我的例子)没有问题。如果有必要,我会尝试发现如何设置它。

      【讨论】:

        【解决方案4】:

        有几种方法可以处理这个问题。用户配置文件有一个职位描述,并且该职位描述有一个库列表。我会为您的 JDBC 连接设置用户配置文件/职位描述组合。

        如果这还不够动态,请考虑编写一个您可以调用的存储过程,它将按照您需要的方式设置库列表。

        另一种方法可能太不灵活,但我提到它作为替代方法。对于服务程序,不要使用 *LIBL,而是指定库。一方面,这使得在测试和生产中无法使用相同的程序。另一方面,它使某人无法在中间插入自己的库。

        如果您真的陷入困境并且 IBM 方面没有人能够为您进行更改,您可以CALL QCMDEXC as a stored procedure 并自己从客户端更改库列表。这是最不可取的,因为它意味着客户端和服务器之间的紧密耦合。如果 IBM 团队真的要设置测试环境(或灾难恢复环境!),您将不得不更改客户端代码中的所有引用并将更改分发给使用它的每个人。

        【讨论】:

          猜你喜欢
          • 2013-02-19
          • 2017-01-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多