在使用存储过程中,我们有时需要传递可变数组,存在两种情况,存储过程有输入或输出参数为自定义可变数组的。在java代码中,如何正确调用oracle存储过程的自定义可变数组类型,在这里做一下示例说明.
java调用oracle存储过程的自定义类型:
plsql定义字符串和数值型可变数组:
一。定义全局类型:
CREATE OR REPLACE TYPE USERSEQID_ARRAY IS VARRAY(50000) OF NUMBER(9)
CREATE OR REPLACE TYPE USERNAME_ARRAY AS VARRAY(32) of varchar(32)
CREATE OR REPLACE TYPE USERPWD_ARRAY AS VARRAY(50000) of varchar(60)
二。java调用输出参数为自定义数组的存储过程:
2.1 输出参数为自定义数组的存储过程make_logincard_pro:
procedure
make_logincard_pro ( p_cardsuitcode
in
varchar
, p_userseqidArr out USERSEQID_ARRAY , p_usernameArr out USERNAME_ARRAY )
IS
v_addedtime date:
=
sysdate;
BEGIN
FOR
ii
IN
1
..
10
LOOP
IF
p_userseqidArr
IS
NULL
THEN
p_userseqidArr :
=
USERSEQID_ARRAY(ii);
ELSE
p_userseqidArr.EXTEND; --超过数组定义大小(50000)将抛出异常 p_userseqidArr(ii) :
=
ii;
END
IF
;
IF
p_usernameArr
IS
NULL
THEN
p_usernameArr :
=
USERSEQID_ARRAY(ii
||
'
TT
'
);
ELSE
p_usernameArr.EXTEND; --超过数组定义大小(32)将抛出异常 p_usernameArr(ii) :
=
ii
||
'
TT
'
;
END
IF
;
END
LOOP
END
make_logincard_pro ;
2.2JAVA调用存储过程make_logincard_pro:
//
代码片段
Connection con
=
session.connection(); java.sql.CallableStatement cst
=
con prepareCall(
"
call CNBT.test_pro(?,?,?)
"
); cst.setString(
1
, cardSuitCode); cst.registerOutParameter(
2
, OracleTypes.ARRAY,
"
USERSEQID_ARRAY
"
); cst.registerOutParameter(
3
, OracleTypes.ARRAY,
"
USERNAME_ARRAY
"
); java.sql.Array userSeqIdArr
=
cst.getArray(
2
); java.sql.Array userNameArr
=
cst.getArray(
3
);
if
( userSeqIdArr
!=
null
)
...
{ BigDecimal userSeqIdList[] = (BigDecimal[])userSeqIdArr.getArray(); // 数据库的number映射为BigDecimal // 。。。。。。 }
if
( userNameArr
!=
null
)
...
{ String userNameList[] = (String[])userNameArr.getArray(); // 。。。。。。 }
三. java调用输入参数为自定义数组的存储过程:
3.1 输入参数为自定义数组的存储过程update_logincard_pwd:
/**/
/* ********************************************* * update_logincard_pwd * *功能描述:更新密码存储过程 * *输入参数: * *输出参数: * *作者:hanjiong * ********************************************** */
procedure
update_logincard_pwd ( p_userSeqIdList
in
USERSEQID_ARRAY, p_userPwdList
in
USERPWD_ARRAY, p_resultcode out
number
);
3.2 java调用存储过程update_logincard_pwd:
//
代码片段
.......................... Connection con
=
session.connection();
//
使用的weblogic数据源
oracle.jdbc.OracleCallableStatement cst2
=
(oracle.jdbc.OracleCallableStatement)con .prepareCall(
"
call CNBT.update_logincard_pwd(?,?,?)
"
); weblogic.jdbc.wrapper.Connection weblogicConn
=
(weblogic.jdbc.wrapper.Connection)con; oracle.jdbc.OracleConnection oracleConn
=
(oracle.jdbc.OracleConnection)weblogicConn.getVendorConnection();
//
转化connection
oracle.sql.ArrayDescriptor des_USERSEQID_ARRAY
=
oracle.sql.ArrayDescriptor.createDescriptor(
"
USERSEQID_ARRAY
"
,oracleConn); oracle.sql.ArrayDescriptor des_USERPWD_ARRAY
=
oracle.sql.ArrayDescriptor.createDescriptor(
"
USERPWD_ARRAY
"
,oracleConn); oracle.sql.ARRAY ora_array1
=
new
oracle.sql.ARRAY(des_USERSEQID_ARRAY, oracleConn, userAccSeqIdArr); oracle.sql.ARRAY ora_array2
=
new
oracle.sql.ARRAY(des_USERPWD_ARRAY, oracleConn, userPwdList); cst2.setArray(
1
, ora_array1); cst2.setArray(
2
, ora_array2); cst2.registerOutParameter(
3
, java.sql.Types.INTEGER); cst2.execute(); updateCode
=
cst2.getInt(
3
); ..................................... ....................................
因为我使用的是weblogic配置的数据源,在取得的connection对象时需要注意,通过数据源取得的Connection对象为weblogic.jdbc.wrapper.Connection,所以不能直接转化为oracle.jdbc.OracleConnection,否则会出现java.lang.ClassCastException异常,所以我们要通过weblogic.jdbc.wrapper.Connection.getVendorConnection()取得java.sql.Connection,在强制转化为oracle.jdbc.OracleConnection。
通过上述两种情况,就可以在Oracle存储过程中使用zid