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

          java調oracle存儲過程

          Posted on 2009-08-12 11:46 leekiang 閱讀(1419) 評論(2)  編輯  收藏 所屬分類: oraclejdbc、事務、并發
          ??????? 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");//第一個問號表示返回結果
          ?? ??? ??? ?cst.setString(2, userid);//第二個問號
          ?? ??? ??? ?cst.executeUpdate();//哪怕是個查詢也用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處,可能會報
          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應用下的classes12.jar,而是加載了weblogic81\server\lib里的ojdbc14.jar,
          ?? ?而ojdbc14.jar里沒有oracle.gss.util.NLSError。
          ?? ?修改classpath先加載classes12.jar,打印出來的是亂碼,只出現亂碼,這次沒有出現類似這樣的異常java.sql.SQLException:?? Non?? supported?? character?? set:?? oracle-character-set-850? 。
          ?? ?還需要修改classpath先加載nls_charset12.jar;(必須這樣,光放在web應用的lib下或光放在weblogic81\server\lib都
          ?? ?不行,jar包放置或加載的這三種方式是有區別的)
          問題:如果使用的是ojdbc.jar,我覺得可能就不要nls_charset12.jar了,并且不需要new oracle.sql.CHAR(values[i],dbCharset)來轉換
          ?? ?
          http://topic.csdn.net/t/20051110/17/4385336.html
          ?? ?類是通過類加載器classloader載入的。 ?
          ? 缺省情況下web容器遵循java的標準標準類載入機制?? --?? 由現載入父加載器level的類。 ?
          ? weblogic的web容器的classloader繼承自ejb容器的classloader,ejb容器的classloader又繼承自 application?? classloader--該loader負責加載classpath下面的類,所以缺省情況下classpath下面的類會被優先載入,即使相同的類存在于web應用的lib目錄。 ?
          ? 可以通過配置文件來修改這種加載順序,使得lib目錄中的類得到優先調用,在weblogic?? 8.1中,方法是在weblogic.xml中加入下面的代碼段: ?
          ? <container-descriptor> ?
          ? <prefer-web-inf-classes>true</prefer-web-inf-classes> ?
          ? </container-descriptor>? ?
          ? weblogic?? 的加載順序就是weblogic?? classpath優先?
          ?
          ?
          ? 一下見http://www.javaeye.com/topic/21141
          ? ClassNotFoundException發生在裝入階段。
          當應用程序試圖通過類的字符串名稱,使用常規的三種方法裝入類,但卻找不到指定名稱的類定義時就拋出該異常。

          NoClassDefFoundError: 當目前執行的類已經編譯,但是找不到它的定義時

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

          創建測試用表

          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、相應的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)中的數值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程序如下:

          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中的換行是無效的,要換行的時候一定要空格結尾,特別是你直接復制代碼的時候!



          評論

          # re: java調oracle存儲過程  回復  更多評論   

          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調oracle存儲過程  回復  更多評論   

          2010-01-12 19:24 by leekiang

          http://zhouyq.javaeye.com/blog/240440
          主站蜘蛛池模板: 哈密市| 大名县| 五指山市| 永州市| 彰武县| 长岭县| 曲沃县| 凤庆县| 宿州市| 遂川县| 青铜峡市| 孝昌县| 太保市| 阿城市| 凉山| 兴安盟| 星子县| 广东省| 罗甸县| 上思县| 麻江县| 巩留县| 东丽区| 宾川县| 庆城县| 德阳市| 和政县| 永城市| 准格尔旗| 扬州市| 海城市| 新竹县| 区。| 南康市| 水城县| 密山市| 潢川县| 彝良县| 双鸭山市| 安化县| 凤山市|