我有一个从IBM系统上的DB2发送数据到RHEL系统上的PostgreSQL服务器的项目,我使用一个触发器将信息发送到数据队列,然后读取数据队列,并使用SQL语句通过RPGLE上的JDBC连接发送到PostgreSQL服务器。
代码大致如下所示(出于安全原因,我不得不删除实际的列名和表名):
dcl-proc doPostgreConn export;
dcl-pi doPostgreConn like(connection) end-pi;
//Code to change and set CLASSPATH variable, if necessary is here
//...
prop = JDBC_Properties();
JDBC_setProp(prop: 'user' : 'user');
JDBC_setProp(prop: 'password' : 'password');
JDBC_setProp(prop: 'databaseName' : 'database');
JDBC_setProp(prop: 'loggerLevel' : 'TRACE' );
JDBC_setProp(prop: 'loggerFile' : '/home/PostgreSQL/log');
pgconn = JDBC_ConnProp('org.postgresql.Driver'
:'jdbc:postgresql://[some_IP]:5432/database'
: prop );
JDBC_freeProp(prop);
return pgconn;
end-proc;
dcl-proc doPGWriteMyTable export;
dcl-pi doPGWriteMyTable like(success);
i#schm char(10);
i#rec char(334);
end-pi;
dcl-ds record extname('MYTABLE') end-ds;
dcl-s prepStmtTxt varchar(10000);
record = i#rec;
pgconn = doPostgreConn;
if pgconn = *NULL;
//Custom Error Handling
endif;
prepStmtTxt = 'INSERT INTO ' + %trim(i#schm) + '.MYTABLE ' +
' VALUES (?, ?, ?) ';
if PGWriteMYTABLEPrep = *NULL;
PGWriteMYTABLEPrep = JDBC_PrepStmt(pgconn:prepStmtTxt);
if PGWriteMYTABLEPrep = *NULL;
endif;
endif;
JDBC_setString (PGWriteMYTABLEPrep: 1: StrCol);
JDBC_setDecimal (PGWriteMYTABLEPrep: 2: DecCol);
JDBC_setDate (PGWriteMYTABLEPrep: 75: DateCol);
if JDBC_execPrepUpd( PGWriteMYTABLEPrep ) < 0;
//Custom Error Handling
endif;
JDBC_Close(pgconn);
return *on;
end-proc;
dcl-proc doPGDeleteMYTABLE export;
dcl-pi doPGDeleteMYTABLE like(success);
i#schm char(10);
i#rec char(334);
end-pi;
dcl-ds record extname('MYTABLE') end-ds;
dcl-s sqlstmt varchar(32000);
dcl-s deleteSuccess ind;
record = i#rec;
sqlstmt = 'DELETE FROM ' + %trim(i#schm) + '.MYTABLE WHERE '; //Basically the key
pgconn = doPostgreConn;
if JDBC_ExecUpd(pgconn:sqlstmt) < 0;
//Custom error handling
endif;
DoPostgreClose(pgconn);
return *on;
end-proc;
数据队列读取程序本质上依次调用DoPGDeleteMYTABLE和DoPGWriteMYTABLE(没有唯一键,因此我们只需要删除PostgreSQL服务器上所有匹配的记录,然后重新添加它们)。
问题是,当数据队列读取程序运行时,第一个循环工作得非常好,然后失败了,顺序如下:
1.更新记录
1.删除任何现有PG记录:成功的
1.准备写入语句:成功的
1.将任何现有DB2记录写入PG:成功的
1.更新记录
1.删除任何现有PG记录:成功的
1.准备语句:成功的
1.将任何现有DB2记录写入PG:* 不成功 *
1.重复5到8,直到数据队列作业重新启动
我收到的错误不是很有帮助。AS400上的作业日志只是告诉我
org.postgresql.util.PSQLException: This connection has been closed.
即使我可以看到PostgreSQL服务器上打开的连接,从RPGLE关闭它仍然有效。
JDBC作业日志没有告诉我写操作发生前后的任何信息,它只是说准备成功了,然后就什么都没有了。
版本信息:
IBM操作系统7.4
基于x86_64-redhat-linux-gnu的PostgreSQL 13.7,由gcc(GCC)11.2.1 20220127(红帽11.2.1 - 9)编译,64位
PostgreSQL JDBC驱动程序postgresql-42.2.19
RPGLE正在利用Scott Klement的JDBCR4
我在网上找到的任何东西都还没有帮助解决这个问题。如果有任何其他我可以提供或尝试,以获得更多信息,请让我知道。
1条答案
按热度按时间jq6vz3qz1#
我没有看到任何东西跳出来的代码,你已经张贴,但鉴于它的工作第一次失败的第二次,我猜有些东西是重置(或不重置)之间的循环。
就我个人而言,我建议在DELETE/WRITE过程之外打开连接;但我不认为这是个骗局。
“连接关闭”很有趣...可能值得运行通信跟踪,看看连接是否实际上正在关闭,如果是,从哪一边关闭。
注意,虽然我喜欢RPG,但我不喜欢从RPG调用Java。很久很久以前我做过一些基准测试,让一个小的Java应用程序处理JDBC比从RPG使用它要快得多。
您还可以考虑使用一种开放源代码的替代方法来直接从RPG调用Java。
AppServer4RPG
应用程序服务器使Java组件可用于IBM i RPG程序,运行在IBM i或任何其他Java平台上。与ArdGate打包,使用IBM i的所有本机SQL接口访问任何JDBC数据库。
ArdGate基本上将其自身注册为DRDA应用程序请求驱动程序(ARD),并允许您像与任何其他远程DRDA(aka Db2)数据库一样与任何JDBC数据库通信。
这意味着,您可以从绿色屏幕STRSQL读/写PostgreSQL。