我不知道我做的这件事情是否还有其他人成功做过,但这篇文章里记录的方法你在metalink或者google上是找不到的,因为这来源于我这几天以来不断的艰苦尝试。
在这篇文章里,我们利用oracle里的java存储过程成功连上了db2 v9 for z/OS,并且执行了sql和其中的一个db2存储过程。
这个问题来源于我现在正在做的项目的需要,我们需要连主机并执行主机里的存储过程。当然,.net前台或者java前台连主机是没问题的,但是我们还是希望能够在oracle数据库端直连db2 v9 for z/OS,因为这样可以减少前台同oracle数据库端的交互并且可以避免冗余代码。
第一个思路是安装Transparent Gateway(即tg4drda),安装完后发现连db2 v9 for z/OS是没问题的,也能读出其中表里的数据,但就是不能执行其中的存储过程。这大致是因为10gR2的tg4drda不支持LOB的缘故,oracle的tg4drda的文档里明确指出:
When the gateway receives a call to run a stored procedure on the DRDA Server (for example DB2/OS390), it first does a lookup of the procedure name in the server catalog. The information that defines a stored procedure is stored in different forms on each DRDA Server. For example, DB2/OS390 V5.0 uses the table SYSIBM.SYSPROCEDURES, while DB2/OS390 V6.1 uses the table SYSIBM.SYSROUTINES.
在db2 v9的SYSIBM.SYSROUTINES里新引入了一个LOB列,这大概就是10gR2的tg4drda不能执行db2 v9 for z/OS里的存储过程的原因。
第二个思路就是使用java存储过程,因为JDBC驱动应该是能连上db2 v9 for z/OS的,但是我在实际用的过程中发现oracle里并不自带JDBC for db2的驱动,所以在缺省情况下,你在oracle的java存储过程里是连不上db2的。
怎么办?
我们现在来想办法把JDBC for db2的驱动加载到oracle里。
如下是一个完整的例子,就以这个当作是给需要的朋友们的新年礼物 :)
1、找到所需要的JDBC for db2的驱动
安装"DB2 Connect Personal Edition V9.1 for Windows(32-bit)",装完后从安装路径(我的是D:\Program Files\IBM\SQLLIB\java)下把db2java.zip、db2jcc.jar、db2jcc_license_cu.jar、db2jcc_javax.jar、db2jcc_license_cisuz.jar拷到$ORACLE_HOME /jdbc/lib下。
2、用loadjava把上述驱动导入到oracle中,注意这里要以sys用户执行导入,导入的过程中会出一些错误,没关系,可以忽略掉,导入的语法为:
loadjava -user sys/oracle@ipratest /u01/app/oracle/product/
loadjava -user sys/oracle@ipratest /u01/app/oracle/product/
loadjava -user sys/oracle@ipratest /u01/app/oracle/product/
loadjava -user sys/oracle@ipratest /u01/app/oracle/product/
loadjava -user sys/oracle@ipratest /u01/app/oracle/product/
3、然后在sys用户下写java存储过程和wrapper function,注意一定要是在sys用户下,否则用不了JCC驱动,核心的代码为:
DriverManager.registerDriver(new com.ibm.db2.jcc.DB2Driver());
conn = DriverManager.getConnection("jdbc:db2://
//执行一个db2存储过程----------begin------------------------------
callname = "{CALL " + ProcedureName + "(?,?)}";
proc = conn.prepareCall(callname);
proc.setString(1, InputString);
proc.registerOutParameter(2, Types.VARCHAR);
proc.execute();
OutputString = proc.getString(2);
//执行一个db2存储过程----------End--------------------------------
//执行一个sql-----------------begin------------------------------
Statement st = conn.createStatement();
String sqlStr= Sqltext;
ResultSet rs = st.executeQuery(sqlStr);
while (rs.next())
{
OutputString = rs.getString(1);
}
//执行一个sql------------------End---------------------------------
4、测试一下调wrapper function的效果,我这里写了两个wrapper function,分别是F_SYS_CALL_DB2_BY_SQL和F_SYS_CALL_DB2_PROC。其中F_SYS_CALL_DB2_BY_SQL是在db2 v9 for z/OS上执行一个我传入的sql语句,并返回查询的结果;F_SYS_CALL_DB2_PROC是在db2 v9 for z/OS上执行一个我传入的db2存储过程,它的输入参数是要调用的db2存储过程的名字,输出参数就是执行这个db2存储过程后的返回值,我们来实际看一下效果:
首先我在一个安装了tg4drda的库里执行一个sql:
SQL> select deptname from DSN8910.DEPT@plhi3 where deptno='A00';
DEPTNAME
------------------------------------------------------------------------
SPIFFY COMPUTER SERVICE DIV.
这里的plhi3就是指向db2 v9 for z/OS的db link,可以看到查询结果为SPIFFY COMPUTER SERVICE DIV。
然后我在未安装tg4drda的库里执行我写好的F_SYS_CALL_DB2_BY_SQL:
SQL> set serveroutput on size 1000000;
SQL> var vc_return_flag varchar2(2000);
SQL> begin
2 :vc_return_flag := F_SYS_CALL_DB2_BY_SQL('select deptname from DSN8910.DEPT where deptno=''A00''');
3 end;
4 /
PL/SQL procedure successfully completed
vc_return_flag
---------
SPIFFY COMPUTER SERVICE DIV.
可以看到返回的结果与tg4drda的结果一致,即我们已经通过java存储过程连上了db2 v9 for z/OS.
Leave a comment