JAVA调用存储过程: 几经挫折,但总算搞通了,为了避免后来者少走弯路,特记述与此,同时亦对自己进行鼓励。
创建测试用表:
CREATE
TABLE
T_TEST( I_ID
NVARCHAR
(
20
), I_NAME
NVARCHAR
(
20
) )
一:无返回值的存储过程
1、在SQL*PLUS中建立存储过程:
CREATE
OR
REPLACE
PROCEDURE
TESTA(PARA1
IN
VARCHAR2
,PARA2
IN
VARCHAR2
)
AS
BEGIN
INSERT
INTO
T_TEST (I_ID,I_NAME)
VALUES
(PARA1, PARA2);
END
TESTA;
2、相应的JAVA程序:
package
com.my.test;
import
java.sql.
*
;
import
java.io.OutputStream;
import
java.io.Writer;
import
java.sql.PreparedStatement;
import
java.sql.ResultSet;
import
oracle.jdbc.driver.
*
;
public
class
TestProcedureOne
...
{ public TestProcedureOne() ... { } public static void main(String[] args ) ... { String driver = " oracle.jdbc.driver.OracleDriver " ; String strUrl = " jdbc:oracle:thin:@192.168.10.216:1521:ctbu " ; Statement stmt = null ; ResultSet rs = null ; Connection conn = null ; CallableStatement cstmt = null ; try ... { Class.forName(driver); conn = DriverManager.getConnection(strUrl, " dbname " , " password " ); CallableStatement proc = null ; proc = conn.prepareCall( " { call dbname.TESTA(?,?) } " ); proc.setString( 1 , " 100 " ); proc.setString( 2 , " TestOne " ); proc.execute(); } catch (SQLException ex2) ... { ex2.printStackTrace(); } catch (Exception ex2) ... { ex2.printStackTrace(); } finally ... { try ... { if (rs != null ) ... { rs.close(); if (stmt != null ) ... { stmt.close(); } if (conn != null ) ... { conn.close(); } } } catch (SQLException ex1) ... { } } } }
二:有返回值的存储过程(非列表)
1、存储过程为:
CREATE
OR
REPLACE
PROCEDURE
TESTB(PARA1
IN
VARCHAR2
,PARA2 OUT
VARCHAR2
)
AS
BEGIN
SELECT
INTO
PARA2
FROM
TESTTB
WHERE
I_ID
=
PARA1;
END
TESTB;
2、JAVA代码:
package
com.my.test;
public
class
TestProcedureTWO
...
{ public TestProcedureTWO() ... { } public static void main(String[] args ) ... { String driver = " oracle.jdbc.driver.OracleDriver " ; String strUrl = " jdbc:oracle:thin:@192.168.10.216:1521:ctbu " ; Statement stmt = null ; ResultSet rs = null ; Connection conn = null ; try ... { Class.forName(driver); conn = DriverManager.getConnection(strUrl, " dbname " , " password " ); CallableStatement proc = null ; proc = conn.prepareCall( " { call HYQ.TESTB(?,?) } " ); proc.setString( 1 , " 100 " ); proc.registerOutParameter( 2 , Types.VARCHAR); proc.execute(); String testPrint = proc.getString( 2 ); System.out.println( " =testPrint=is= " + testPrint); } catch (SQLException ex2) ... { ex2.printStackTrace(); } catch (Exception ex2) ... { ex2.printStackTrace(); } finally ... { try ... { if (rs != null ) ... { rs.close(); if (stmt != null ) ... { stmt.close(); } if (conn != null ) ... { conn.close(); } } } catch (SQLException ex1) ... { } } } }
}
注意,这里的proc.getString(2)中的数值2并非任意的,而是和存储过程中的out列对应的,如果out是在第一个位置,那就是proc.getString(1),如果是第三个位置,就是proc.getString(3),当然也可以同时有多个返回值,那就是再多加几个out参数了。 三:返回列表
由于oracle存储过程没有返回值,它的所有返回值都是通过out参数来替代的,列表同样也不例外,但由于是集合,所以不能用一般的参数,必须要用pagkage了.所以要分两部分。 1、在SQL*PLUS中建一个程序包
CREATE
OR
REPLACE
PACKAGE TESTPACKAGE
AS
TYPE Test_CURSOR
IS
REF
CURSOR
;
procedure
TESTC(cur_ref out Test_CURSOR);
end
TESTPACKAGE;
建立存储过程,存储过程为:
create
or
replace
package body TESTPACKAGE
as
procedure
TESTC(cur_ref out Test_CURSOR)
is
begin
OPEN
cur_ref
FOR
SELECT
*
FROM
T_TEST;
end
TESTC;
END
TESTPACKAGE;
可以看到,它是把游标(可以理解为一个指针),作为一个out 参数来返回值的。
JAVA程序如下:
package
com.my.test;
import
java.sql.
*
;
import
java.io.OutputStream;
import
java.io.Writer;
import
java.sql.PreparedStatement;
import
java.sql.ResultSet;
import
oracle.jdbc.driver.
*
;
public
class
TestProcedureOne
...
{ public TestProcedureOne() ... { } public static void main(String[] args ) ... { String driver = " oracle.jdbc.driver.OracleDriver " ; String strUrl = " jdbc:oracle:thin:@192.168.10.216:1521:ctbu " ; Statement stmt = null ; ResultSet rs = null ; Connection conn = null ; CallableStatement cstmt = null ; try ... { Class.forName(driver); conn = DriverManager.getConnection(strUrl, " databasename " " password " ); CallableStatement proc = null ; proc = conn.prepareCall( " { call cqsb.TESTA(?,?) } " ); proc.setString( 1 , " 100 " ); proc.setString( 2 , " TestOne " ); proc.execute(); } catch (SQLException ex2) ... { ex2.printStackTrace(); } catch (Exception ex2) ... { ex2.printStackTrace(); } finally ... { try ... { if (rs != null ) ... { rs.close(); if (stmt != null ) ... { stmt.close(); } if (conn != null ) ... { conn.close(); } } } catch (SQLException ex1) ... { } } } }
特别注意: 1、在执行前一定要先把oracle的驱动包放到class路径里。
2、Toad在我建立存储过程中搞了很多莫名的错误,多数是没有创建成功而不报错,或者是创建有误而不提示,应当引起重视。所以最好还是在SQL*PLUS玩这些。
3、在SQL*PLUS中的换行是无效的,要换行的时候一定要空格结尾,特别是你直接复制代码的时候!