我正在编写一个小的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)。 原因 . . : RPG 程序在程序 INTERFACCE/TRG_F4104A 中TRG_F4104A 语句 152 尝试调用程序或过程 *LIBL/WS_MATERI,但 无法访问程序或过程、库或所需的 服务计划。如果名称为 *N,则调用是过程绑定调用 指针。
恢复 . . . : 检查作业日志以获取有关 原因的详细信息 错误并联系负责程序维护的人员。 回复消息的可能选择 . .:
D -- 获取 RPG 格式的转储。
S -- 获取系统转储。
我的问题是:如何指定触发需求的其他库?在我的工具的旧版本(用Delphi编写)中,我使用了Client/Access ODBC,其中有一个特殊的字段,您可以在其中输入其他库,但现在我不知道该怎么做。
AS400 (iSeries) 允许在 jdbc URL 中使用逗号分隔的库列表:
JDBC:AS400://someserver;命名=系统;库=开发文件,产品文件,系统IBM等
命名=系统表示SQL将使用库列表。例如:
select * from NUMEAN13
命名=SQL 表示 SQL 将包含表引用中前缀的库名称。例如:
select * from INTERFACCE.NUMEAN13
我的经验是你不能把它们混在一起。如果使用库列表(命名=系统),则所有 sql 都不得包含库名称。如果使用非库列表 (nameing=sql),则所有 sql 都必须包含库名称。
有几种方法可以解决这个问题。 用户配置文件具有作业描述,该作业描述具有库列表。 我会为您的JDBC连接设置用户配置文件/职位描述组合。
如果这还不够动态,请考虑编写一个可以调用的存储过程,该过程将根据需要设置库列表。
另一种方式可能太不灵活,但我提到它是一种替代方案。 不要将 *LIBL 用于服务程序,而是指定库。 一方面,这使得在测试和生产中无法使用相同的程序。 另一方面,它使某人无法在中间插入自己的库。
如果您真的陷入困境,并且 IBM 端没有人能够为您进行更改,则可以调用 QCMDEXC 作为存储过程,并从客户端自行更改库列表。 这是最不希望的,因为它意味着客户端和服务器之间的紧密耦合。 如果 IBM 团队真的要设置测试环境(或灾难恢复环境!),则必须更改客户端代码中的所有引用,并将更改分发给使用它的每个人。
感谢您的提示。
我也在考虑使用存储过程(如您所建议的),但最终我发现使用其他 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,但是如果您使用标准端口(如我的情况),则没有问题。如果有必要,我会尝试发现如何设置它。
几个解决方案。
快速实时修复将触发器程序复制到 QGPL(临时修复。 需要尽快实施永久修复)
或
更改用于连接到AS400的用户配置文件的JOBD,使其具有正确的列表。 用于 JDBC 的用户配置文件应该已经被锁定,或者它是组中用户的 jdbc,所以这是一个简单的 CHGJOBD JOBD(x) LIBL(xxx xxx xxx xxx),但连接必须回收。
或
更改触发器程序,使其具有硬编码库。 我敢打赌,您需要对该文件的独占访问权限。 我没有工作(无法访问 iseries),所以我无法验证此解决方案。
我建议不要更改连接字符串。 您最终将不得不为连接到数据库的每台计算机更改它。