调用Java存储过程遇到SQL4306N时怎么办
发布网友
发布时间:2022-04-22 09:25
我来回答
共2个回答
热心网友
时间:2022-04-09 06:54
本文讲解了在开发Java存储过程时经常会碰到的一个问题及其解决办法。
inginStr,intinStart,intinNum)
throwsException
{
if(inStart<1||inStart>inStr.length()||inNum<=0)outStr="";
if((inStart-1+inNum)>inStr.length())inNum=inStr.length()+1-inS
tart;
outStr=inStr.substring(inStart-1,inStart+inNum-1);
}
}
2.创建存储过程的DDL语句(SpTest.db2):
DROPSPECIFICPROCEDURETESTSUB@
CREATEPROCEDUREsubString(OUTOUTSTRINGVARCHAR(500),ININSTRINGVARCHAR(500),I
NINSTARTINT,ININNUMINT)
SPECIFICTESTSUB
DYNAMICRESULTSETS0
DETERMINISTIC
LANGUAGEJAVA
PARAMETERSTYLEJAVA
NODBINFO
FENCED
THREADSAFE
3.编译并定义Java存储过程:
$javacSpTest.java
$cpSpTest.class~/sqllib/function
$db2connecttosample
DatabaseConnectionInformation
Databaseserver=DB2/60008.2.0
SQLauthorizationID=XXXX
Localdatabasealias=SAMPLE
$db2-td@-vfSpTest.db2
DROPSPECIFICPROCEDURETESTSUB
DB21034EThecommandwasprocessedasanSQLstatementbecauseitwasnota
validCommandLineProcessorcommand.DuringSQLprocessingitreturned:
SQL0204N"XXXX.TESTSUB"isanundefinedname.SQLSTATE=42704
CREATEPROCEDUREsubString(OUTOUTSTRINGVARCHAR(500),ININSTRINGVARCHAR(500),I
NINSTARTINT,ININNUMINT)
SPECIFICTESTSUB
DYNAMICRESULTSETS0
DETERMINISTIC
LANGUAGEJAVA
PARAMETERSTYLEJAVA
NODBINFO
FENCED
THREADSAFE
EXTERNALNAME'SpTest.subString'
DB20000ITheSQLcommandcompletedsuccessfully.
$db2"callsubString(?,'sdafatewfdsa',2,5)"
SQL4306NJavastoredprocereoruser-definedfunction"XXXX.SUBSTRING",
specificname"TESTSUB"couldnotcallJavamethod"subString",signature
"([Ljava/lang/String;Ljava/lang/Strin".SQLSTATE=42724
我们经过检查,发现类名正确、类库也在目录$HOME/sqllib/function下。这时我们集中精力检查程序的签名(Signature)。因为在错误信息中,签名不全,我们要查看$DB2DIAGPATH/db2diag.log文件(其中$DB2DIAGPATH代表数据库管理器配置参数中的DIAGPATH参数)。我们看到完整的签名为:
2005-08-17-14.47.19.569936+480I126072C540LEVEL:Warning
PID:1810588TID:1287PROC:db2fmp(Java)0
INSTANCE:XXXXNODE:000
FUNCTION:DB2UDB,BSUJavasupport,sqlejCallJavaRoutine_dll,probe:150
MESSAGE:JNIGetMethodIDfailed.signature:
DATA#1:Hexmp,42bytes
0x3007A950:285B4C6A6176612F6C616E672F537472([Ljava/lang/Str
0x3007A960:696E673B4C6A6176612F6C616E672F53ing;Ljava/lang/S
0x3007A970:7472696E673B49492956tring;II)V
这是DB2用来查找Java存储过程对应的方法时用的签名(Signature),此时我们再检查一下类文件中SubString方法的签名:
$cd~/sqllib/function
$javap-sSpTest
Thisutilitycanbeusedtoreverseassemblecode.Manyprogramlicense
agreementsdonotpermitreverseassembly.Ifyouarenotthecopyright
ownerofthecodewhichyouwanttoreverseassemble,pleasecheckthe
licenseagreementunderwhichyouacquiredsuchcodetoconfirmwhether
youarepermittedtoperformsuchreverseassembly.
CompiledfromSpTest.java
publicclassSpTestextendsjava.lang.Object{
publicSpTest();
/*()V*/
publicstaticvoidsubString(java.lang.String,java.lang.String,int,int)t
hrowsjava.lang.Exception;
/*(Ljava/lang/String;Ljava/lang/String;II)V*/
我们看到在Java类中的函数签名与DB2查找的函数签名不一致。这就是SQL4306N产生的原因。
第一个参数不一样。根据JNI规范,[Ljava/lang/String是一个String数组。而Ljava/lang/String则是字符串String类型,也就是我们程序源文件中定义的类型。那为什么DB2要查找一个String数组类型的参数呢?通过查找DB2文档,我们发现如下解释(http://publib.boulder.ibm.com/infocenter/db2help/topic/com.ibm.db2.udb.doc/admin/r0008328.htm):
PARAMETERTYPEJAVA
ThismeansthattheprocerewilluseaparameterpassingconventionthatconformstotheJavalanguageandSQLJRoutinesspecification.IN/OUTandOUTparameterswillbepassedassingleentryarraystofacilitatereturningvalues.ThiscanonlybespecifiedwhenLANGUAGEJAVAisused.
我们看到如果创建存储过程时使用了IN/OUT以及OUT参数,DB2会将其解释为一个单项数组,并通过单项数组传递返回值。因此,我们同样需要在Java程序中使用字符串数组来返回我们的结果。
修改后的java源程序如下所示:
importjava.lang.*;
importjava.io.*;
publicclassSpTest
{
publicstaticvoidsubString(String[]outStr,StringinStr,intinStart,intin
Num)
throwsException
{
if(inStart<1||inStart>inStr.length()||inNum<=0)outStr[0]="";
if((inStart-1+inNum)>inStr.length())inNum=inStr.length()+1-inS
tart;
outStr[0]=inStr.substring(inStart-1,inStart+inNum-1);
}
}
此时我们重新编译并创建存储过程,可以看到,它可以正确执行了。
$javacSpTest.java
$cpSpTest.class~/sqllib/function
$db2-td@-vfSpTest.db2
DROPSPECIFICPROCEDURETESTSUB
DB20000ITheSQLcommandcompletedsuccessfully.
CREATEPROCEDUREsubString(OUTOUTSTRINGVARCHAR(500),ININSTRINGVARCHAR(500),I
NINSTARTINT,ININNUMINT)
SPECIFICTESTSUB
DYNAMICRESULTSETS0
DETERMINISTIC
LANGUAGEJAVA
PARAMETERSTYLEJAVA
NODBINFO
FENCED
THREADSAFE
EXTERNALNAME'SpTest.subString'
DB20000ITheSQLcommandcompletedsuccessfully.
$db2"callsubstring(?,'sadfdsafdsaf',2,5)"
Valueofoutputparameters
ParameterName:OUTSTRING
ParameterValue:adfds
ReturnStatus=0
关于SQL4306N的错误,基本上通过上面的步骤就可以解决了。如果您的问题通过上面的检查方法还没有解决,请联系IBM技术支持人员。
热心网友
时间:2022-04-09 08:12
首先单独执行一下你的存储过程是否可以运行,如果运行成功,在代码中看一下你的传入参数是否正确