MDA/MDD/TDD/DDD/DDDDDDD
          posts - 536, comments - 111, trackbacks - 0, articles - 0
            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

          java調(diào)oracle存儲過程

          Posted on 2009-08-12 11:46 leekiang 閱讀(1419) 評論(2)  編輯  收藏 所屬分類: oraclejdbc、事務(wù)、并發(fā)
          ??????? OracleCallableStatement cst = null;
          ?? ??? ?int oracleId = CharacterSet.ZHS16GBK_CHARSET;
          ?? ??? ?oracle.sql.CharacterSet dbCharset = oracle.sql.CharacterSet.make(oracleId);
          ?? ??? ??? ?cst = (OracleCallableStatement) conn
          ?? ??? ??? ??? ??? ?.prepareCall("begin ?:= pkg_test.f_getList(?); end;");
          //String sql = "{?=call PckgStudSltCourse.addStudPreSltCourse(?,?,?,?)}";也可以這樣寫
          //sql="{call sp(?,?,?,?,?)}";//如果無返回值
          ?? ??? ??? ?cst.registerOutParameter(1, OracleTypes.ARRAY, "T_ARRAY");//第一個(gè)問號表示返回結(jié)果
          ?? ??? ??? ?cst.setString(2, userid);//第二個(gè)問號
          ?? ??? ??? ?cst.executeUpdate();//哪怕是個(gè)查詢也用executeUpdate

          ?? ??? ??? ?oracle.sql.ARRAY simpleArray = cst.getARRAY(1);//從statement獲取,而不是rs
          ?? ??? ??? ?String[] values = (String[]) simpleArray.getArray();
          ?? ??? ??? ?for (int i = 0; i < values.length; i++) {
          ?? ??? ??? ??? ?oracle.sql.CHAR out_value = new oracle.sql.CHAR(values[i],dbCharset);
          ?? ??? ??? ??? ?System.out.println(out_value.stringValue());
          ?? ??? ??? ?}
          ?? ??? ??? ?
          注意:在new oracle.sql.CHAR處,可能會(huì)報(bào)
          java.lang.NoClassDefFoundError: oracle/gss/util/NLSError
          ?? ?at oracle.sql.CharacterSetUnknown.failCharsetUnknown(CharacterSetFactoryThin.java:178)
          ?? ?at oracle.sql.CharacterSetUnknown.convert(CharacterSetFactoryThin.java:145)
          ?? ?at oracle.sql.CHAR.(CHAR.java:147)
          ?? ?即missing some jar file in runtime environment
          ?? ?原因是weblogic沒有加載web應(yīng)用下的classes12.jar,而是加載了weblogic81\server\lib里的ojdbc14.jar,
          ?? ?而ojdbc14.jar里沒有oracle.gss.util.NLSError。
          ?? ?修改classpath先加載classes12.jar,打印出來的是亂碼,只出現(xiàn)亂碼,這次沒有出現(xiàn)類似這樣的異常java.sql.SQLException:?? Non?? supported?? character?? set:?? oracle-character-set-850? 。
          ?? ?還需要修改classpath先加載nls_charset12.jar;(必須這樣,光放在web應(yīng)用的lib下或光放在weblogic81\server\lib都
          ?? ?不行,jar包放置或加載的這三種方式是有區(qū)別的)
          問題:如果使用的是ojdbc.jar,我覺得可能就不要nls_charset12.jar了,并且不需要new oracle.sql.CHAR(values[i],dbCharset)來轉(zhuǎn)換
          ?? ?
          http://topic.csdn.net/t/20051110/17/4385336.html
          ?? ?類是通過類加載器classloader載入的。 ?
          ? 缺省情況下web容器遵循java的標(biāo)準(zhǔn)標(biāo)準(zhǔn)類載入機(jī)制?? --?? 由現(xiàn)載入父加載器level的類。 ?
          ? weblogic的web容器的classloader繼承自ejb容器的classloader,ejb容器的classloader又繼承自 application?? classloader--該loader負(fù)責(zé)加載classpath下面的類,所以缺省情況下classpath下面的類會(huì)被優(yōu)先載入,即使相同的類存在于web應(yīng)用的lib目錄。 ?
          ? 可以通過配置文件來修改這種加載順序,使得lib目錄中的類得到優(yōu)先調(diào)用,在weblogic?? 8.1中,方法是在weblogic.xml中加入下面的代碼段: ?
          ? <container-descriptor> ?
          ? <prefer-web-inf-classes>true</prefer-web-inf-classes> ?
          ? </container-descriptor>? ?
          ? weblogic?? 的加載順序就是weblogic?? classpath優(yōu)先?
          ?
          ?
          ? 一下見http://www.javaeye.com/topic/21141
          ? ClassNotFoundException發(fā)生在裝入階段。
          當(dāng)應(yīng)用程序試圖通過類的字符串名稱,使用常規(guī)的三種方法裝入類,但卻找不到指定名稱的類定義時(shí)就拋出該異常。

          NoClassDefFoundError: 當(dāng)目前執(zhí)行的類已經(jīng)編譯,但是找不到它的定義時(shí)

          也就是說你如果編譯了一個(gè)類B,在類A中調(diào)用,編譯完成以后,你又刪除掉B,運(yùn)行A的時(shí)候那么就會(huì)出現(xiàn)這個(gè)錯(cuò)誤
          當(dāng)你使用字符串去轉(zhuǎn)換類,也就是嘗試使用Class.forName等方法去獲得一個(gè)類的時(shí)候,如果這個(gè)類不存在,就會(huì)拋出ClassNotFoundException。
          ?? 而你編譯的類無錯(cuò),但是在運(yùn)行時(shí)刻,缺乏某些必須的類時(shí),就是拋出NoClassDefFoundError。這種情況最常見就是你在編譯時(shí),在classpath下有這個(gè)類,但是在運(yùn)行時(shí),你的classpath缺少這個(gè)類。
          ? ?
          ? 加載時(shí)從外存儲器找不到需要的class就出現(xiàn)ClassNotFoundException
          ? 連接時(shí)從內(nèi)存找不到需要的class就出現(xiàn)NoClassDefFoundError
          ? 問題:加載和連接的區(qū)別

          創(chuàng)建測試用表

          CREATETABLE T_TEST(
          I_ID
          NVARCHAR(20),
          I_NAME
          NVARCHAR(20)
          )

          一:無返回值的存儲過程

          1、建立存儲過程
          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、相應(yīng)的JAVA程序
          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代碼
          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)中的數(shù)值2并非任意的,而是和存儲過程中的out列對應(yīng)的,如果out是在第一個(gè)位置,那就是 proc.getString(1),如果是第三個(gè)位置,就是proc.getString(3),當(dāng)然也可以同時(shí)有多個(gè)返回值,那就是再多加幾個(gè)out 參數(shù)了。

          三:返回列表
          由于oracle存儲過程沒有返回值,它的所有返回值都是通過out參數(shù)來替代的,列表同樣也不例外,但由于是集合,所以不能用一般的參數(shù),必須要用pagkage了.所以要分兩部分。
          1、在SQL*PLUS中建一個(gè)程序包

          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;
          可以看到,它是把游標(biāo)(可以理解為一個(gè)指針),作為一個(gè)out 參數(shù)來返回值的。
          JAVA程序如下:

          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、在執(zhí)行前一定要先把oracle的驅(qū)動(dòng)包放到class路徑里。
          2、Toad在我建立存儲過程中搞了很多莫名的錯(cuò)誤,多數(shù)是沒有創(chuàng)建成功而不報(bào)錯(cuò),
          或者是創(chuàng)建有誤而不提示,應(yīng)當(dāng)引起重視。所以最好還是在SQL*PLUS玩這些。
          3、在SQL*PLUS中的換行是無效的,要換行的時(shí)候一定要空格結(jié)尾,特別是你直接復(fù)制代碼的時(shí)候!



          評論

          # re: java調(diào)oracle存儲過程  回復(fù)  更多評論   

          2010-01-12 19:18 by leekiang
          //如果java代碼是utf-8編碼,則不需要ZHS16GBK_CHARSET和new oracle.sql.CHAR(values[i],dbCharset)了:
          如下:
          ARRAY a= cst.getARRAY(1);
          Datum[] data = a.getOracleArray();
          for (int i = 0; i < data.length; i++) {
          System.out.println(
          new String(data[i].shareBytes()));
          }

          # re: java調(diào)oracle存儲過程  回復(fù)  更多評論   

          2010-01-12 19:24 by leekiang

          http://zhouyq.javaeye.com/blog/240440
          主站蜘蛛池模板: 辰溪县| 县级市| 台湾省| 永州市| 安泽县| 锡林浩特市| 浦北县| 尉犁县| 朝阳县| 武功县| 济阳县| 聂荣县| 博客| 滦南县| 衡水市| 安庆市| 南京市| 砚山县| 宾阳县| 陆河县| 兰考县| 宝应县| 土默特右旗| 汉沽区| 江陵县| 浦江县| 奇台县| 乐平市| 中牟县| 辽宁省| 望都县| 龙门县| 新河县| 霍邱县| 永昌县| 富蕴县| 汤原县| 武山县| 河南省| 思茅市| 增城市|