<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆-25  評論-6  文章-0  trackbacks-0

    在數據庫應用程序中使用存儲過程有許多好處,包括減少對網絡的使用、提高性能以及降低開發成本。Java 存儲過程是 DB2 支持的最流行的例程之一。原因之一是,由于 Java 編程語言非常流行,所以 Java 開發人員非常多。因此,在有多種語言可供選擇時,Java 例程往往是首選的。

    DB2 存儲過程不一定非用 Java 來編寫。如果業務邏輯只需要簡單的存儲過程,那么可以考慮用 SQL Procedure Language(SQL PL)進行存儲過程開發。SQL 存儲過程總是作為 受信任的 存儲過程運行,并且因為它們不依賴于外部 Java 虛擬機(Java Virtual Machine,JVM)進程來裝載過程,所以比 Java 例程快。

    使用 Java 存儲過程的好處與創建 Java 應用程序時獲得的好處相同。Java 是非常安全的編程語言。用戶只能獲得 Java 字節碼。Java 代碼編譯一次,就能夠在支持 JVM 的任何計算機和操作系統上運行。因為 Java 代碼在單獨的 JVM 中運行,所以 JVM 能夠正確地處理(可能導致 JVM 崩潰的)危險操作。不需要實現單獨的基礎設施來處理危險狀況,因為 Java 具有捕獲異常的內置機制。

    在本文中,我們有時將 Java 存儲過程稱為例程。在 DB2 UDB 中存儲過程和例程是同義的。在 DB2 V8 中引入了例程的概念,它既表示存儲過程,也表示用戶定義函數(UDF)。

    本文討論在開發或運行 Java 存儲過程的過程中可能遇到的常見錯誤消息。在開始討論之前,我們先討論 Java 存儲過程開發的重要概念和配置參數。接下來,描述如何啟用 DB2 Java。需要建立 Java 環境才能成功地調用 Java 存儲過程。





    回頁首


    關鍵概念

    以下概念對于理解存儲過程在 DB2 環境中如何工作非常重要:

    • FENCED 或 NOT FENCED: 這個子句指定例程是否被認為可以在數據庫管理器操作環境的進程或地址空間中“安全地”運行。

      如果存儲過程被注冊為 FENCED,那么數據庫管理器就禁止過程訪問它的內部資源(比如數據緩沖區)。大多數例程都有作為 FENCED 或 NOT FENCED 運行的選項。但是,Java 例程只能注冊為 FENCED。一般來說,作為 FENCED 運行的例程執行得沒有作為 NOT FENCED 運行的相似例程那么快。這是因為 NOT FENCED 例程可以在數據庫引擎內利用進程間通信(IPC)。

      對沒有經過徹底測試的例程使用 NOT FENCED,可能會破壞 DB2 完整性。DB2 對于許多常見的意外故障類型采取了某些保護措施,但是在使用 NOT FENCED 例程時無法保證完全的完整性。NOT FENCED 例程常常被稱為受信任的(trusted)。聲明為受信任的例程在數據庫管理器的地址空間中運行。

      將例程注冊為 NOT FENCED 需要 SYSADM 特權、DBADM 特權或一個特殊的特權(CREATE_NOT_FENCED)。定義為 NOT THREADSAFE 的例程只能指定 FENCED。

    • THREADSAFE 或 NOT THREADSAFE: 這個子句指定這個例程是否可以安全地在其他例程的進程中執行(THREADSAFE 是可以,NOT THREADSAFE 是不可以)。

      如果過程定義為 THREADSAFE,數據庫管理器就可以在其他例程的進程中調用這個過程。一般來說,要想定義為 THREADSAFE,例程不應該使用任何全局或靜態數據區域。許多編程參考資料討論了如何編寫線程安全的例程。FENCED 和 NOT FENCED 過程都可以是 THREADSAFE 的。

      如果過程定義為 NOT THREADSAFE,數據庫管理器就絕不會在其他例程的進程中調用這個過程。

      在 Java 存儲過程中,THREADSAFE 是默認的,無論它被聲明為 FENCED 還是 NOT FENCED 存儲過程。





    回頁首


    配置參數

    DB2 有許多配置參數。一些參數在數據庫級上定義,其他參數在數據庫管理級上定義。影響存儲過程行為的大多數參數是在實例級(即數據庫管理級)上定義的。

    • KEEPFENCED: 這是一個數據庫管理器配置(DBM CFG)參數。在以前的 DB2 UDB 版本中,它被稱為 KEEPDARI。這個參數指出,在完成一個防護模式例程調用之后,是否保留防護模式進程(db2fmp)。防護模式進程是作為單獨的系統實體創建的,以便將用戶編寫的防護模式代碼與數據庫管理器代理進程隔離開來。這個參數只能應用于數據庫服務器。在開發存儲過程時,強烈建議將這個參數設置為 NO,這樣,調用存儲過程時總會得到全新的存儲過程副本。如果存儲過程常常重新編譯,那么這特別重要。在生產環境中,應該將這個參數設置為 YES,因為它會顯著地影響性能。NOT FENCED 存儲過程不受這個配置參數影響,因為它們不在 db2fmp 進程中運行。
    • FENCED_POOL: 這是一個數據庫管理器配置(DBM CFG)參數。它代表系統上緩存的空閑防護模式進程(db2fmp)的數量。對于線程化的 db2fmp 進程(為線程安全的存儲過程和 UDF 提供服務的進程),這個參數代表每個 db2fmp 進程中緩存的線程數量。對于非線程化的 db2fmp 進程,這個參數代表緩存的進程數量。
    • NUM_INITFENCED: 這是一個數據庫管理器配置(DBM CFG)參數。這個參數表示在 DB2START 時在 db2fmp 池中創建的非線程化空閑 db2fmp 進程的初始數量。如果沒有指定 KEEPFENCED,這個參數就被忽略。
    • JDK_PATH: 這是一個數據庫管理器配置(DBM CFG)參數。這個參數指出用來執行 Java 存儲過程的 JVM 或 Java Development Kit(JDK)的位置。這是一個非常重要的參數。它的值應該設置為包含 JVM Java 可執行文件的 “bin” 目錄的上一級目錄的完整路徑。在 Windows? 平臺上的一個例子是 C:\Program Files\IBM\SQLLIB\java\jdk。UNIX? 例子是 /usr/java1.3.1。JVM 級別也非常重要,因為根據使用的 db2level 和平臺級別,DB2 UDB 只支持某些 JVM 級別。(這個問題將在本文稍后討論。)
    • JAVA_HEAP_SZ: 這是一個數據庫管理器配置(DBM CFG)參數。這個參數決定為 Java 存儲過程和 UDF 服務的 Java 解釋器所使用的堆的最大大小。為了避免在 Java 存儲過程中耗盡內存,可以增加這個值。但是,如果在環境中要調用許多存儲過程(即,每個 JVM 都會分配這么多堆空間),那么分配太多內存也是有害的。一般規則是保持 JAVA_HEAP_SZ 為默認設置,即 512(4K 頁)。
    • ASLHEAPSZ: 這是一個數據庫管理器配置(DBM CFG)參數。應用程序支持層堆是本地應用程序和與它相關聯的代理之間的通信緩沖區。這個緩沖區作為每個數據庫管理器代理共享的內存分配。這個參數確定緩沖區的大小,用于在例程和發出調用的應用程序之間傳遞參數。存儲過程中的參數數量和參數大小明確地影響這個配置參數。系統上允許同時存在的 db2fmp 進程的最大數量也受這個參數的影響。
    • QUERY_HEAP_SZ: 這是一個數據庫管理器配置(DBM CFG)參數。這個參數指定可以分配給查詢堆的最大內存量。查詢堆用于在代理的私有內存中存儲每個查詢。每個查詢的信息包括輸入和輸出 SQLDA、語句文本、SQLCA、包名、創建者、區號和一致性符號。提供這個參數是為了確保應用程序不會不必要地消耗代理中的大量虛擬內存。如果這個參數設置得過低,那么執行復雜 SQL 的存儲過程會導致 db2fmp 進程意外終止。
    • DB2_FMP_COMM_HEAPSZ: 這是一個 db2set 注冊表參數。這個參數可應用于所有平臺,只有 AIX 32 位平臺除外,在這種平臺上這個值預定義為 256MB。這個變量指定防護例程調用(比如存儲過程或用戶定義函數調用)所使用的池的大小(以 4 KB 頁為單位)。每個防護例程所使用的空間是 ASLHEAPSZ 配置參數值的兩倍。如果在系統上運行大量防護例程,那么可能需要增加這個變量的值。如果運行的防護例程很少,可以降低這個值。將這個值設置為 0 就表示不創建池,因此不能調用防護例程。可以用以下公式計算系統上可以同時運行的 db2fmp 進程的數量:
      
      
      Maximum Number of db2fmps = DB2_FMP_COMM_HEAPSZ / (2*ASLHEAPSZ)





    回頁首


    設置 Java 環境

    需要執行幾個步驟,然后才能編譯 Java 存儲過程。本節討論設置用于運行 Java 過程的系統所需的步驟。

    兼容的 JDK/JVM 級別

    在開始之前,首先確保數據庫服務器上安裝了兼容的 JDK/JVM。每種操作系統支持不同的 JDK 級別。如果數據庫實例配置為 64 位而不是 32 位,那么這特別重要。

    支持的 JDK/JVM 級別的兼容性表可以在以下網頁上找到:http://www-306.ibm.com/software/data/db2/udb/ad/v8/java/

    同一個系統上可以安裝多個 JVM。為了決定在執行 Java 存儲過程時使用哪個 JVM,DB2 讀取 JDK_PATH 數據庫管理器配置參數。需要確保 JDK_PATH 指向與環境兼容的 JVM。

    設置 Java 環境

    DB2 數據庫服務器的平臺需要正確地設置才能使用 Java。對于 Java 支持,每種平臺可能有自己的需求。

    對于 UNIX 平臺一般的 Java 設置需求可以在以下網頁上找到:http://publib.boulder.ibm.com/infocenter/db2help/topic/com.ibm.db2.udb.doc/ad/t0004675.htm

    對于 Windows 平臺一般的 Java 設置需求可以在以下網頁上找到:http://publib.boulder.ibm.com/infocenter/db2help/topic/com.ibm.db2.udb.doc/ad/t0006428.htm

    HPUX 和 Linux

    HPUX 和 Linux 對于 Java 支持有額外的需求:

    防護 id

    為了執行 FENCED 存儲過程,DB2 通過防護 id 方式提供了額外的安全層。這個 id(和組)應該在創建 DB2 實例時創建。可以從以下網頁獲得關于這個 id 的更多信息:http://publib.boulder.ibm.com/infocenter/db2help/topic/com.ibm.db2.udb.doc/admin/t0005077.htm

    配置參數

    前面的 配置參數 小節提到了一組重要的配置參數。大多數這些參數可以保持默認設置。但是,當遇到問題(特別是性能問題或內存問題)時,應該檢查和調整 DB2 配置參數,使之適合您的系統,這是非常重要的。

    數據庫特權

    在大多數情況下,應用程序開發人員將開發存儲過程。這一般意味著 DB2 管理員可能必須向應用程序開發人員提供必需的特權,讓他們能夠創建和維護這些存儲過程。對于 Java 存儲過程開發人員,可考慮提供以下特權:EXECUTE、CREATE_EXTERNAL_ROUTINE、CREATE_NOT_FENCED_ROUTINE、IMPLICIT_SCHEMA、CREATEIN 和 BINDADD。關于數據庫特權的更多信息,請參閱:http://publib.boulder.ibm.com/infocenter/db2help/topic/com.ibm.db2.udb.doc/admin/c0005524.htm





    回頁首


    創建和部署 Java 例程

    設置好環境之后,就應該能夠創建和部署自己的 Java(或 SQLJ)存儲過程。DB2 Application Development Client(如果安裝了)包含一組示例,您在初次創建存儲過程時可以參考這些示例。Java 存儲過程示例位于 sqllib/samples/java/jdbc 目錄中,稱為 SpServer.java。SQLJ 存儲過程示例位于 sqllib/samples/java/sqlj 目錄,稱為 SpServer.sqlj。

    編寫自己的例程

    在編寫自己的存儲過程時需要考慮一些事情。需要決定為存儲過程采用哪種參數傳遞技術。DB2 UDB 對于 Java 應用程序支持兩種參數風格:

    • PARAMETER STYLE JAVA —— 這意味著存儲過程將使用符合 Java 語言和 SQLJ 例程規范的參數傳遞約定。IN/OUT 和 OUT 參數將作為單項數組傳遞,以便于返回值。這只能在使用 LANGUAGE JAVA 時指定。PARAMETER STYLE JAVA 過程不支持 DBINFO 或 PROGRAM TYPE 子句。
    • PARAMETER STYLE DB2GENERAL —— 這意味著存儲過程將使用為 Java 方法定義的參數傳遞約定。這只能在使用 LANGUAGE JAVA 時指定。PARAMETER STYLE DB2GENERAL 仍然可以用于在 Java 例程中啟用以下特性的實現:表函數、scratchpad、對 DBINFO 結構進行訪問以及對函數或方法進行 FINAL CALL(和單獨的首次調用)。為了使用 DB2GENERAL 參數風格,需要確保存儲過程的類擴展了 COM.ibm.db2.app.StoredProc。關于 PARAMETER STYLE DB2GENERAL 的更多信息,請參閱:http://publib.boulder.ibm.com/infocenter/db2help/topic/com.ibm.db2.udb.doc/ad/c0000420.htm

    在 CREATE 語句中使用 PARAMETER STYLE JAVA 子句注冊 Java 例程。

    與其他任何應用程序一樣,存儲過程需要一個 Connection context。在 Java 和 JDBC 中,這是使用來自 java.sql.* 類的 Connection 對象完成的。調用存儲過程的應用程序將建立連接。所以在 Java 存儲過程中,以默認連接 方式建立連接,如清單 1 所示。


    清單 1. 一個名為 INSERT_JAVASP 的示例存儲過程
    																				
    
    
    
    1   //The simplest JAVA SP
    
    2   import java.sql.*;
    
    3 
    
    4   public class INSERT_JAVASP
    
    5   {
    
    6     public static void iNSERT_JAVASP  (String input) throws SQLException,
    
     	Exception
    
    7     {
    
    8       int errorCode;
    
    9  
    
    10      try
    
    11      {
    
    12        // get caller's connection to the database
    
    13   Connection con = DriverManager.getConnection("jdbc:default:connection");
    
    14     
    
    15        String query = "INSERT INTO CWYLAW.StoreData (c) VALUES (?)";
    
    16
    
    17        PreparedStatement pstmt = con.prepareStatement(query);
    
    18        pstmt.setString(1, input);
    
    19        pstmt.executeUpdate();
    
    20  
    
    21      }   
    
    22      catch (SQLException sqle)
    
    23      {
    
    24        errorCode = sqle.getErrorCode();
    
    25        throw new SQLException( errorCode   " FAILED" ); 
    
    26      }
    
    27    }
    
    28  }
    																		

    在清單 1 的第 13 行上,Connection 對象(con)被建立為 “默認” 連接。調用存儲過程的應用程序將在調用過程之前建立這個連接。使用默認連接時,存儲過程從調用者那里獲得它的連接屬性。這里顯示的例子是一個 Java 存儲過程,它接受一個輸入參數并且將其值插入 CWYLAW.StoreData 表。

    對于使用例程的限制

    對于為 DB2 UDB 開發存儲過程,有幾個限制。一定要檢查 DB2 Infocenter 的以下部分,確保自己了解這些限制:http://publib.boulder.ibm.com/infocenter/db2help/topic/com.ibm.db2.udb.doc/ad/c0009198.htm

    Java 類型映射

    Java 支持自己的一組數據類型。DB2 也有自己的一組數據類型。例如,DB2 數據類型 VARCHAR 在 Java 中不存在。但是,Java 有一個 String 對象,可以替代這種數據類型。DB2 UDB 有一組 “首選的” 數據類型映射,適用于 Java 應用程序和存儲過程。表 1(引用于 Infocenter —— 參見 參考資料)顯示了這些映射。

    Java 數據類型映射
    SQL 類型 JDBC 2.0 類型 Java 類型
    BIGINT BIGINT long
    BLOB BLOB java.sql.Blob
    CHAR CHAR String
    CHAR FOR BIT DATA BINARY byte[]
    CLOB CLOB java.sql.Clob
    DATE DATE java.sql.Date
    DBCLOB CLOB java.sql.Clob
    DECIMAL DECIMAL java.math.BigDecimal
    DOUBLE DOUBLE double
    FLOAT FLOAT double
    INTEGER INTEGER int
    GRAPHIC CHAR String
    LONG VARCHAR LONGVARCHAR String
    LONG VARCHAR FOR BIT DATA LONGVARBINARY byte[]
    LONGVARGRAPHIC LONGVARCHAR String
    NUMERIC NUMERIC java.math.BigDecimal
    REAL REAL float
    SMALLINT SMALLINT short
    TIME TIME java.sql.Time
    TIMESTAMP TIMESTAMP java.sql.Timestamp
    VARCHAR VARCHAR String
    VARCHAR FOR BIT DATA VARBINARY byte[]
    VARGRAPHIC VARCHAR String

    編譯例程

    創建了存儲過程之后,需要對它進行編譯。使用系統上安裝的 JDK,用以下命令對過程進行編譯:javac INSERT_JAVASP.java

    這生成一個類文件。可以將這個類文件轉移到 sqllib/function 目錄(這是 DB2 獲得存儲過程可執行文件的默認位置),也可以將它轉移到您選擇的另一個位置(并且在 CREATE PROCEDURE 命令中使用這個定制的路徑)。

    另一個辦法是將類文件打包到 JAR 文件中,并且部署 JAR 文件。可以使用以下命令將類文件打包到 JAR 文件中:jar -cvf INSERT_JAVASP.jar INSERT_JAVASP.class

    關于放置 Java 類的位置的更多信息,請閱讀 Infocenter 的以下部分:http://publib.boulder.ibm.com/infocenter/db2help/topic/com.ibm.db2.udb.doc/ad/c0006348.htm.

    SQLJ 例程

    在編寫 SQLJ 存儲過程時,需要執行兩個額外的步驟:

    • 使用 DB2 SQLJ Translator 翻譯 SQLJ 源代碼。這會將 sqlj 代碼轉換成 java 代碼,并且創建一個 SQLJ 可序列化(.ser)文件。
    • 定制這個可序列化文件,使嵌入語句的訪問計劃被存儲到包中(或綁定文件中)。這需要使用 db2sqljcustomize 命令。

    關于 SQLJ 的更多信息,請參閱:http://publib.boulder.ibm.com/infocenter/db2help/topic/com.ibm.db2.udb.doc/ad/t0007588.htm

    數據庫服務器上的 JAR 文件管理

    如果使用 JAR 文件而不是類文件,就需要采取一些額外的步驟,使 DB2 認識到 JAR 文件是存儲過程類的容器。DB2 附帶四個內置的存儲過程,幫助管理 JAR 文件。

    • SQLJ.INSTALL_JAR :這將把 JAR 文件 “安裝” 到 DB2 中,這樣,當 DB2 類裝載器尋找要裝載的存儲過程庫時,它會找到并且裝載這個存儲過程(而不是同名的另一個存儲過程)。
      語法:CALL sqlj.install_jar( jar-url, jar-id )
    • SQLJ.REPLACE_JAR:這將用一個新副本 “替換” DB2 中的 JAR 文件。如果存儲過程近來由于任何變更而重新編譯過,那么這個操作特別有用。這樣,DB2 類裝載器將在運行時重新裝載具有新內容的 JAR 文件并且使用新內容。
      語法:CALL sqlj.replace_jar( jar-url, jar-id )
    • SQLJ.REMOVE_JAR:這將從 DB2 實例中 “刪除” JAR 文件。如果您打算刪除存儲過程并且不會重新創建它,那么這個操作就有用了。這樣,DB2 就不會在內存中保留這個 JAR 文件的副本。
      語法:CALL sqlj.remove_jar( jar-id )
    • SQLJ.REFRESH_CLASSES:這將在 DB2 實例中 “刷新” 一個 JAR 文件中包含的所有類。當更新 Java 例程類時,需要這樣做。這使 DB2 裝載新的類。如果沒有使用這個命令,DB2 將使用類的舊版本。這可以與 SQLJ.REPLACE_JAR 結合使用。
      語法:CALL sqlj.refresh_classes( void )

    關于 JAR 文件管理的更多信息,請參閱:http://publib.boulder.ibm.com/infocenter/db2help/topic/com.ibm.db2.udb.doc/ad/r0006425.htmhttp://publib.boulder.ibm.com/infocenter/db2help/topic/com.ibm.db2.udb.doc/ad/t0006410.htm

    注冊例程

    在編譯了存儲過程(并且可選地將它存儲在 JAR 文件中),并將它轉移到某個位置之后,可以對存儲過程進行注冊,使應用程序可以引用它。

    為此,需要使用 CREATE PROCEDURE 語句。在 CREATE PROCEDURE 語句中,可以為存儲過程指定幾個選項。下面是其中幾個重要的選項:

    • SPECIFIC:這在 DB2 編目中惟一地標識存儲過程名。一般來說,“SPECIFIC” 名稱匹配存儲過程名。
    • DYNAMIC RESULT SETS:這決定存儲過程是否返回一個結果集。存儲過程也可能返回多個結果集。這個選項決定過程將返回多少結果集。
    • LANGUAGE:這應該設置為 JAVA。對于 SQLJ 存儲過程,也使用 JAVA。
    • EXTERNAL NAME:這個參數決定某個存儲過程的類文件或 JAR 文件的位置以及文件內的方法。文件的默認位置是 sqllib/function 文件夾。也可以指定文件實際位置的完整路徑。EXTERNAL NAME 子句的格式如下: ‘jar-id!class_id.method_id’‘class_id.method_id’
    • FENCED / NOT FENCED:這個參數決定存儲過程是聲明為 FENCED,還是 NOT FENCED。只有在您認為代碼能夠安全執行的情況下,才應該使用 NOT FENCED 存儲過程。
    • THREADSAFE / NOT THREADSAFE:這個參數決定 FENCED 存儲過程的執行是否是線程安全的。這只對定義為 FENCED 的過程起作用,因為 NOT FENCED 過程總被定義為 THREADSAFE。
    • PARAMETER STYLE:對于 Java 例程,參數風格只能是 PARAMETER STYLE JAVA 或 PARAMETER STYLE DB2GENERAL。

    關于 CREATE PROCEDURE 語句的更多信息,請參閱:http://publib.boulder.ibm.com/infocenter/db2help/topic/com.ibm.db2.udb.doc/admin/r0008328.htm

    清單 2 顯示一個 CREATE PROCEDURE 語句示例,其中使用了一些選項。


    清單 2. CREATE PROCEDURE 語句示例
    																				
    
    
    
    CREATE PROCEDURE INSERT_JAVASP (IN INPUT CHAR(3))
    
    SPECIFIC INSERT
    
    DYNAMIC RESULT SETS 0
    
    DETERMINISTIC
    
    LANGUAGE JAVA
    
    PARAMETER STYLE JAVA
    
    NO DBINFO
    
    FENCED
    
    THREADSAFE
    
    MODIFIES SQL DATA
    
    PROGRAM TYPE SUB
    
    EXTERNAL NAME 'INSERT_JAVASP!iNSERT_JAVASP'
    
    ;
    																		

    調用例程

    一旦對存儲過程進行了注冊,首先要做的是調用它,確保它按照預期和設計進行工作。DB2 有一個 “CALL” 命令,可以使用它調用任何存儲過程。在大多數情況下,希望讓應用程序使用參數標志等動態地調用存儲過程。請閱讀 Application Development Guide,以便確定從應用程序中調用過程的最佳方式。

    然而,DB2 命令行處理程序(CLP)可以使用以下語法調用存儲過程:
    CALL proc-name( [parm1, parm2...] )
    其中的 parm1、parm2 等等是參數。如果參數是基于字符的輸入參數,那么在單引號中指定字面值。如果參數是基于數值的輸入參數,那么按原樣指定字面值。如果參數是輸出參數,那么使用‘?’字符表示輸出參數。例如:

    																				
    
    $ db2 "CALL SHAKEBS.TESTPROC('hello', 'world', 1, 2.5, ?, 'testing')"
    																		

    在這個例子中,一共有 6 個參數。第一個、第二個和第六個參數都是字符字面值。第三個參數是數值字面值,適用于 integer 或 smallint 這樣的數據類型。第四個參數也是數值字面值,但是因為它包含小數點,所以應該被看作 double、float 或 decimal 類型。因為第五個參數是問號(?),所以它表示輸出參數。因此,當這個存儲過程被調用時,它將在這個輸出參數中返回一個值。

    關于 “CALL” 命令的更多信息,請參閱:http://publib.boulder.ibm.com/infocenter/db2help/topic/com.ibm.db2.udb.doc/ad/t0011378.htmhttp://publib.boulder.ibm.com/infocenter/db2help/topic/com.ibm.db2.udb.doc/ad/t0009000.htmhttp://publib.boulder.ibm.com/infocenter/db2help/topic/com.ibm.db2.udb.doc/ad/t0007055.htm





    回頁首


    常見問題

    現在,讓我們看看應用程序開發人員在開發和執行 Java(或 SQLJ)存儲過程時可能遇到的一些常見問題。本文的 下載 小節中的一個 zip 文件提供了所有例子。請注意,這些例子中大部分都要求在服務器上的數據庫管理器配置文件中設置 KEEPFENCED=NO

    SQL4301 RC=0

    清單 3 顯示第一個錯誤的例子,sqlcode 為 SQL4301,返回碼為 0。


    清單 3. SQL4301 rc=0 示例 1:Windows 上的 INSERT_JAVASP.java
    																				
    
    
    
    D:\>javac INSERT_JAVASP.java
    
    
    
    D:\>copy INSERT_JAVASP.class "C:\Program Files\IBM\SQLLIB\Function"
    
            1 file(s) copied.
    
    
    
    D:\>db2 -tvf Create.ddl
    
    CREATE PROCEDURE INSERT_JAVASP (IN INPUT CHAR(3))
    
    SPECIFIC INSERT
    
    DYNAMIC RESULT SETS 0
    
    DETERMINISTIC
    
    LANGUAGE JAVA
    
    PARAMETER STYLE JAVA
    
    NO DBINFO
    
    FENCED
    
    THREADSAFE
    
    MODIFIES SQL DATA
    
    PROGRAM TYPE SUB
    
    EXTERNAL NAME 'INSERT_JAVASP!iNSERT_JAVASP'
    
    
    
    DB20000I  The SQL command completed successfully.
    
    
    
    D:\>db2 call INSERT('D')
    
    SQL4301N  Java or .NET interpreter startup or communication failed, reason
    
    code "0".  SQLSTATE=58004
    																		

    這個操作失敗并且顯示 SQL4301 rc=0 錯誤消息。為什么呢?檢查 JDK_PATH 數據庫管理器配置參數的設置是否正確。JDK_PATH 應該設置為用來執行 Java 存儲過程的 JVM/JDK 的 “bin” 的上一級目錄。為了糾正這個問題,檢查數據庫管理器配置參數 JDK_PATH,并且修改它。


    清單 4. SQL4301 rc=0 示例 1:數據庫管理器配置文件的片段
    																				
    
    
    
    D:\>db2 get dbm cfg 
    
    
    
              Database Manager Configuration
    
    
    
         Node type = Enterprise Server Edition with local and remote clients
    
    
    
    Database manager configuration release level         = 0x0a00
    
    
    
    Maximum total of files open            (MAXTOTFILOP) = 16000
    
    CPU speed (millisec/instruction)          (CPUSPEED) = 9.368161e-007
    
    Communications bandwidth (MB/sec)   (COMM_BANDWIDTH) = 1.000000e 002
    
    
    
    Max number of concurrently active databases  (NUMDB) = 8
    
    Data Links support                       (DATALINKS) = NO
    
    Federated Database System Support        (FEDERATED) = NO
    
    Transaction processor monitor name     (TP_MON_NAME) =
    
    
    
    Default charge-back account        (DFT_ACCOUNT_STR) =
    
    
    
    Java Development Kit installation path    (JDK_PATH) = C:\PROGRA~1\IBM\
    
    SQLLIB\java
    
    
    
    ...
    																		

    注意,JDK_PATH 沒有指向 “bin” 的上一級目錄。這需要修改,如清單 5 所示。


    清單 5. SQL4301 rc=0 示例 1:更新數據庫管理器配置文件
    																				
    
    
    
    D:\>db2 update dbm cfg using JDK_PATH C:\PROGRA~1\IBM\SQLLIB\java\jdk
    
    
    
    DB20000I  The UPDATE DATABASE MANAGER CONFIGURATION command 
    
    completed successfully.
    
    
    
    
    
    D:\>db2stop force
    
    09/25/2005 14:33:16     0   0   SQL1064N  DB2STOP processing was successful.
    
    SQL1064N  DB2STOP processing was successful.
    
    
    
    D:\>db2start
    
    09/25/2005 14:33:46     0   0   SQL1063N  DB2START processing was successful.
    
    SQL1063N  DB2START processing was successful.
    
    
    
    D:\>db2 connect to sample
    
    
    
    
    
       Database Connection Information
    
    
    
     Database server        = DB2/NT 8.2.3
    
     SQL authorization ID   = SHAKEBS
    
     Local database alias   = SAMPLE
    
    
    
    D:\>db2 call INSERT_JAVASP('D')
    
    
    
      Return Status = 0
    
    
    
    D:\>db2 "select * from CWYLAW.StoreData"
    
    
    
    C
    
    ---
    
    D
    
    
    
      1 record(s) selected.
    																		

    清單 6 顯示 SQL4301 rc=0 錯誤的另一個例子。這是由于使用了不兼容的 JVM 造成的。64 位實例需要 64 位的 JDK。32 位實例需要 32 位的 JDK。


    清單 6. SQL4301 rc=0 示例 2:在 AIX 上收到 SQL4301 rc=0 錯誤
    																				
    
    
    
    $ which java
    
    /wsdb/v81/bldsupp/AIX/jdk1.4.1/bin/java
    
    
    
    $ java -version
    
    
    
    java version "1.4.1"
    
    Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1)
    
    Classic VM (build 1.4.1, J2RE 1.4.1 IBM AIX build ca1411-20030930 (JIT enabled:
    
    jitc))
    
    
    
    $ db2level
    
    
    
    DB21085I  Instance "dbguest4" uses "64" bits and DB2 code release 
    
    "SQL08022" with level identifier "03030106".
    
    Informational tokens are "DB2 v8.1.1.88", "s050422", "U800789", and FixPak "9".
    
    Product is installed at "/usr/opt/db2_08_01".
    
    
    
    
    
    $ db2 connect to sample
    
    
    
       Database Connection Information
    
    
    
     Database server        = DB2/AIX64 8.2.2
    
     SQL authorization ID   = DBGUEST4
    
     Local database alias   = SAMPLE
    
    
    
    $ db2 "call out_language(?)"
    
    SQL4301N  Java or .NET interpreter startup or communication failed, reason
    
    code "0".  SQLSTATE=58004
    																		

    一旦使用了適合平臺的 JDK 級別,這個錯誤就應該消失了。


    清單 7. SQL4301 rc=0 示例 2:在 AIX 上糾正 SQL4301 rc=0 錯誤
    																				
    
    
    
    $ db2 connect to sample
    
    
    
       Database Connection Information
    
    
    
     Database server        = DB2/AIX64 8.2.2
    
     SQL authorization ID   = DBGUEST4
    
     Local database alias   = SAMPLE
    
    
    
    $ db2 "call out_language(?)"
    
    
    
      Value of output parameters
    
      --------------------------
    
      Parameter Name  : LANGUAGE
    
      Parameter Value : JAVA
    
    
    
      Return Status = 0
    
    
    
    $ which java
    
    /wsdb/v81/bldsupp/AIX5L64/jdk1.4.1/bin/java
    
    
    
    $ java -version
    
    java version "1.4.1"
    
    Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1)
    
    
    
    Classic VM (build 1.4.1, J2RE 1.4.1 IBM AIX 5L for PowerPC (64 bit JVM) 
    
    build ca
    
    ix641411-20030930 (JIT enabled: jitc))
    																		

    常用做法是檢查 db2diag.log 中的重要錯誤消息,由此可以判斷出使用的 JDK 級別不正確。


    清單 8. SQL4301 rc=0 示例 2:db2diag.log 中的相關條目
    																				
    
    
    
    2005-10-02-18.42.36.052560-240 E226800A732        LEVEL: Error (OS)
    
    PID     : 191200               TID  : 1           PROC : db2fmp
    
    INSTANCE: dbguest4             NODE : 000
    
    FUNCTION: DB2 UDB, oper system services, sqloLoadModule, probe:130
    
    CALLED  : OS, -, dlopen
    
    OSERR   : ENOEXEC (8) "Cannot run a file that does not have a valid format."
    
    MESSAGE : Attempt to load specified library failed.
    
    DATA #1 : Library name or path, 55 bytes
    
    /wsdb/v81/bldsupp/AIX/jdk1.4.1/jre/bin/classic/libjvm.a
    
    DATA #2 : shared library load flags, PD_TYPE_LOAD_FLAGS, 4 bytes
    
    2
    
    DATA #3 : String, 145 bytes
    
    
    
    	0509-022 Cannot load module 
    
       /wsdb/v81/bldsupp/AIX/jdk1.4.1/jre/bin/classic/libjvm.a.
    
    	0509-124 The program is a discontinued 64-bit object file.
    
    
    
    2005-10-02-18.42.36.053802-240 E227533A860        LEVEL: Error (OS)
    
    PID     : 191200               TID  : 1           PROC : db2fmp
    
    INSTANCE: dbguest4             NODE : 000
    
    FUNCTION: DB2 UDB, oper system services, sqloLoadModule, probe:140
    
    CALLED  : OS, -, dlopen
    
    OSERR   : ENOEXEC (8) "Cannot run a file that does not have a valid format."
    
    MESSAGE : Attempt to load specified library augmented with object name failed.
    
    DATA #1 : Library name or path, 65 bytes
    
    /wsdb/v81/bldsupp/AIX/jdk1.4.1/jre/bin/classic/libjvm.a(shr_64.o)
    
    DATA #2 : shared library load flags, PD_TYPE_LOAD_FLAGS, 4 bytes
    
    262146
    
    DATA #3 : String, 231 bytes
    
    	0509-022 Cannot load module 
    
    	   /wsdb/v81/bldsupp/AIX/jdk1.4.1/jre/bin/classic/libjvm.a(shr_64.o).
    
    	0509-153   File /wsdb/v81/bldsupp/AIX/jdk1.4.1/jre/bin/classic/libjvm.a is 
    
    	    not an archive or the file could not be read properly.
    
    
    
    2005-10-02-18.42.36.058868-240 I228394A367        LEVEL: Error
    
    PID     : 191200               TID  : 1           PROC : db2fmp
    
    INSTANCE: dbguest4             NODE : 000
    
    FUNCTION: DB2 UDB, oper system services, sqloJVMstart, probe:30
    
    MESSAGE : sqloloadmodule failed.  RC:
    
    DATA #1 : Hexdump, 4 bytes
    
    0x0FFFFFFFFFFFC080 : 870F 009B                                  ....
    
    
    
    2005-10-02-18.42.36.059205-240 I228762A362        LEVEL: Error
    
    PID     : 191200               TID  : 1           PROC : db2fmp
    
    INSTANCE: dbguest4             NODE : 000
    
    FUNCTION: DB2 UDB, oper system services, sqloJAttach, probe:5
    
    MESSAGE : JVM startup failed.  RC:
    
    DATA #1 : Hexdump, 4 bytes
    
    0x0FFFFFFFFFFFF3E0 : FFFF EF34                                  ...4
    
    
    
    2005-10-02-18.42.36.059511-240 I229125A363        LEVEL: Error
    
    PID     : 191200               TID  : 1           PROC : db2fmp
    
    INSTANCE: dbguest4             NODE : 000
    
    FUNCTION: DB2 UDB, BSU Java support, sqlejAttach, probe:10
    
    MESSAGE : Error from sqloJAttach.  RC:
    
    DATA #1 : Hexdump, 4 bytes
    
    0x0FFFFFFFFFFFF4A0 : FFFF EF34                                  ...4
    
    
    
    2005-10-02-18.42.36.060331-240 I229489A372        LEVEL: Severe
    
    PID     : 251500               TID  : 1           PROC : db2agent (SAMPLE)
    
    INSTANCE: dbguest4             NODE : 000         DB   : SAMPLE
    
    APPHDL  : 0-7                  APPID: *LOCAL.dbguest4.051002224226
    
    FUNCTION: DB2 UDB, routine_infrastructure, sqlerGetFmpThread, probe:20
    
    RETCODE : ZRC=0xFFFFFBEE=-1042
    
    
    
    2005-10-02-18.42.36.066498-240 I229862A314        LEVEL: Warning
    
    PID     : 124744               TID  : 1           PROC : db2sysc
    
    INSTANCE: dbguest4             NODE : 000
    
    MESSAGE : Removing FMP from pool
    
    DATA #1 : Hexdump, 16 bytes
    
    0x0FFFFFFFFFFFE090 : 0000 0000 0000 0000 0002 EAE0 0002 49B8    ...I.
    
    
    
    2005-10-02-18.44.20.194287-240 I230177A348        LEVEL: Event
    
    PID     : 120486               TID  : 1           PROC : db2flacc
    
    INSTANCE: dbguest4             NODE : 000
    
    FUNCTION: DB2 UDB, config/install, sqlfLogUpdateCfgParam, probe:30
    
    CHANGE  : CFG DBM: "JDK_path" From: "/wsdb/v81/bldsupp/AIX/jdk1.4.1" To: 
    
        "/wsdb/v81/bldsupp/AIX5L64/jdk1.4.1"
    																		

    SQL4301 RC=2

    本文中沒有為 SQL4301 RC=2 錯誤消息提供例子,但是這種錯誤也值得注意。前面在討論為 Java 存儲過程支持設置環境時提到過,Linux 和 HPUX 平臺需要額外的步驟。如果沒有執行這些額外步驟,就會發生 SQL4301 RC=2 錯誤。如果您使用這些平臺,那么請確保正確地設置了環境。

    SQL4301 RC=4


    清單 9. SQL4301 rc=4 示例:Windows 上的 INSERT_JAVASP.java
    																				
    
    
    
    D:\>javac INSERT_JAVASP.java
    
    
    
    D:\>copy INSERT_JAVASP.class "C:\Program Files\IBM\SQLLIB\Function"
    
            1 file(s) copied.     
    
    
    
    D:\>db2 -tvf Create.ddl
    
    CREATE PROCEDURE INSERT_JAVASP (IN INPUT CHAR(3))
    
    SPECIFIC INSERT
    
    DYNAMIC RESULT SETS 0
    
    DETERMINISTIC
    
    LANGUAGE JAVA
    
    PARAMETER STYLE JAVA
    
    NO DBINFO
    
    FENCED
    
    THREADSAFE
    
    MODIFIES SQL DATA
    
    PROGRAM TYPE SUB
    
    EXTERNAL NAME 'INSERT_JAVASP!iNSERT_JAVASP'
    
    
    
    DB20000I  The SQL command completed successfully.
    
    
    
    
    
    D:\>db2 call INSERT('A')
    
    SQL4301N  Java or .NET interpreter startup or communication failed, 
    
    reason code "4".  SQLSTATE=58004
    																		

    這個操作失敗并且顯示 SQL4301 rc=4 錯誤消息。為什么呢?檢查 JAVA_HEAP_SZ 數據庫管理器配置參數是否足夠大,足以容納您的 Java 存儲過程。JAVA_HEAP_SZ 的默認值(512 個 4KB 頁)應該足夠了,但是如果出現這種錯誤,可以嘗試將這個值加倍。

    關于這個參數的更多信息,請查閱:http://publib.boulder.ibm.com/infocenter/db2help/topic/com.ibm.db2.udb.doc/admin/r0000137.htm


    清單 10. SQL4301 rc=4 示例:數據庫管理器配置文件片段
    																				
    
    
    
    D:\>db2 get dbm cfg 
    
    
    
              Database Manager Configuration
    
    
    
         Node type = Enterprise Server Edition with local and remote clients
    
    
    
     Database manager configuration release level            = 0x0a00
    
    
    
     Maximum total of files open               (MAXTOTFILOP) = 16000
    
     CPU speed (millisec/instruction)             (CPUSPEED) = 9.368161e-007
    
     Communications bandwidth (MB/sec)      (COMM_BANDWIDTH) = 1.000000e 002
    
    
    
    ...
    
    
    
     Database monitor heap size (4KB)          (MON_HEAP_SZ) = 66
    
     Java Virtual Machine heap size (4KB)     (JAVA_HEAP_SZ) = 1
    
     Audit buffer size (4KB)                  (AUDIT_BUF_SZ) = 0
    
     Size of instance shared memory (4KB)  (INSTANCE_MEMORY) = AUTOMATIC
    
     Backup buffer default size (4KB)            (BACKBUFSZ) = 1024
    
     Restore buffer default size (4KB)           (RESTBUFSZ) = 1024
    
    
    
    ...
    
    
    																		

    JAVA_HEAP_SZ 為 1(4K 頁)顯然不夠運行哪怕是最簡單的存儲過程。在大多數情況下,默認設置 512(4K 頁)應該足夠了。在很少見的情況下,可能仍然會出現這個錯誤消息,此時可以考慮將這個配置參數再加倍。


    清單 11. SQL4301 rc=4 示例:更新數據庫管理器配置文件
    																				
    
    
    
    D:\>db2 update dbm cfg using JAVA_HEAP_SZ 512
    
    DB20000I  The UPDATE DATABASE MANAGER CONFIGURATION command completed
    
    successfully.
    
      
    
    D:\>db2stop force
    
    09/25/2005 14:33:16     0   0   SQL1064N  DB2STOP processing was successful.
    
    SQL1064N  DB2STOP processing was successful.
    
    
    
    D:\>db2start
    
    09/25/2005 14:33:46     0   0   SQL1063N  DB2START processing was successful.
    
    SQL1063N  DB2START processing was successful.
    
    
    
    D:\>db2 connect to sample
    
    
    
       Database Connection Information
    
    
    
     Database server        = DB2/NT 8.2.3
    
     SQL authorization ID   = SHAKEBS
    
     Local database alias   = SAMPLE
    
    
    
    D:\>db2 call INSERT_JAVASP('A')
    
    
    
      Return Status = 0
    
    
    
    D:\>db2 "select * from CWYLAW.StoreData"
    
    
    
    C
    
    ---
    
    A
    
    
    
      1 record(s) selected.
    																		

    SQL4301 RC=-4301


    清單 12. SQL4301 rc=-4301 示例:Windows 上的 INSERT_JAVASP.java
    																				
    
    
    
    D:\>javac INSERT_JAVASP.java
    
    
    
    D:\>copy INSERT_JAVASP.class "C:\Program Files\IBM\SQLLIB\Function"
    
            1 file(s) copied.
    
            
    
    D:\>db2 -tvf Create.ddl
    
    CREATE PROCEDURE INSERT_JAVASP (IN INPUT CHAR(3))
    
    SPECIFIC INSERT
    
    DYNAMIC RESULT SETS 0
    
    DETERMINISTIC
    
    LANGUAGE JAVA
    
    PARAMETER STYLE JAVA
    
    NO DBINFO
    
    FENCED
    
    THREADSAFE
    
    MODIFIES SQL DATA
    
    PROGRAM TYPE SUB
    
    EXTERNAL NAME 'INSERT_JAVASP!iNSERT_JAVASP'
    
    
    
    DB20000I  The SQL command completed successfully.
    
    
    
    
    
    D:\>db2 call INSERT('D')
    
    SQL4301N  Java or .NET interpreter startup or communication failed, 
    
    reason code "-4301".  SQLSTATE=58004
    																		

    這個操作失敗并且顯示 SQL4301 rc=-4301 錯誤消息。為什么呢?檢查環境變量 CLASSPATH,確保 db2java.zip 在 CLASSPATH 中。如果 db2java.zip 不在 CLASSPATH 中,就添加它。


    清單 13. SQL4301 rc=-4301 示例:修改 Windows 上的環境變量 CLASSPATH
    																				
    
    
    
    D:>set | more
    
    
    
    ALLUSERSPROFILE=C:\Documents and Settings\All Users
    
    APPDATA=C:\Documents and Settings\Administrator\Application Data
    
    CLASSPATH=.;C:\Progra~1\IBM\SQLLIB\java\db2jcc.jar;C:\Progra~1\IBM\SQLLIB\
    
    java\sqlj.zip;C:\Progra~1\IBM\SQLLIB\java\common.jar;C:\Progra~1\IBM\SQLLIB\
    
    java\db2jcc_license_cisuz.jar;C:\Progra~1\IBM\SQLLIB\java\db2jcc_license_cu.jar
    
    ...
    
    
    
    D:\>set CLASSPATH=%CLASSPATH%;C:\Progra~1\IBM\SQLLIB\java\db2java.zip
    																		

    在這個例子中,我們在命令行上設置 CLASSPATH。這只對您登錄進的用戶會話有效。建議將它添加到全局環境中。在 Windows 上,可以使用 System Control Panel 來完成。在 UNIX 系統上,將 CLASSPATH 添加到用戶帳戶的 .profile 文件中。


    清單 14. SQL4301 rc=-4301 示例:解決了 SQL4301 rc=-4301
    																				
    
    
    
    D:\>db2 call INSERT_JAVASP('D')
    
    
    
      Return Status = 0
    
    
    
    D:\>db2 "select * from CWYLAW.StoreData"
    
    
    
    C
    
    ---
    
    D
    
    
    
      1 record(s) selected.
    																		

    SQL4302

    SQL4302 常常意味著在 Java 存儲過程代碼中捕獲了一個異常,或者發生了錯誤狀況。應該檢查 db2diag.log。在 DIAGLEVEL 3(默認設置)上,db2diag.log 捕獲堆棧跟蹤,甚至給出代碼中捕獲到異常處的行號。下面這個簡單的例子假設編譯了 Query.java 并且將 Query.class 文件復制到了 Windows 計算機的 \sqllib\FUNCTION 目錄中。


    清單 15. SQL4302 示例:Windows 上的 Query.java
    																				
    
       
    
    1    import java.sql.*;
    
    2         
    
    3    public class Query
    
    4    {
    
    5       public static void query ( int id , String[] s1 ) throws 
    
                SQLException, Exception
    
    6      {
    
    7           // Get connection to the database
    
    8           Connection con = 
    
                DriverManager.getConnection("jdbc:default:connection");
    
    9           PreparedStatement stmt = null;
    
    10          String errorLabel =  null;
    
    11          String sql;
    
    12                  
    
    13          
    
    14          sql = "SELECT NAME FROM STAFF WHERE ID = ?";
    
    15          stmt = con.prepareStatement( sql );     
    
    16          stmt.setInt(1, id);   
    
    17          ResultSet rs = stmt.executeQuery();
    
    18                  
    
    19          if (!rs.next()) {
    
    20             // set errorCode to SQL0100 to indicate data not found
    
    21             errorLabel = "SQL0100 : NO DATA FOUND, QUERY RETURNS 
    
                   EMPTY RESULT SET";
    
    22             throw new SQLException(errorLabel);
    
    23          } else {
    
    24             // move to first row of result set
    
    25             s1[0] = rs.getString(1);                
    
    26          }   
    
    27                  
    
    28                  
    
    29          // clean up resources
    
    30          rs.close();
    
    31          stmt.close();
    
    32          con.close();
    
    33                           
    
    34          }
    
    35   }
    
    
    
    D:\>db2 -tvf Create.ddl
    
    CREATE PROCEDURE CWYLAW.QUERY (IN ID INT, OUT NAME CHAR(9))
    
    SPECIFIC QUERY
    
    DYNAMIC RESULT SETS 0
    
    NOT DETERMINISTIC
    
    LANGUAGE JAVA
    
    EXTERNAL NAME 'Query.query'
    
    FENCED
    
    THREADSAFE
    
    PARAMETER STYLE JAVA
    
    
    
    DB20000I  The SQL command completed successfully.
    
    
    
    
    
    D:\>db2 call query(5, ?)
    
    SQL4302N  Procedure or user-defined function "CWYLAW.QUERY", 
    
    specific name "QUERY" aborted with an exception "SQL0100 : 
    
    NO DATA FOUND, QUERY RETURNS EMPTY RESULT".  SQLSTATE=38501
    
    
    
    D:\>db2 call query(10, ?)
    
    
    
      Value of output parameters
    
      --------------------------
    
      Parameter Name  : NAME
    
      Parameter Value : Sanders
    
    
    
      Return Status = 0
    																		

    SQL4302 錯誤并不代表嚴重的錯誤。實際上,這是一個好信號。它意味著 Java 代碼中的異常處理程序工作正常,并且捕獲到了一個異常。在下面您將看到,db2diag.log 實際上告訴您在 Query.java 的第 22 行捕獲了這個異常。在這個例子中 SQL4302 告訴我們,過程中的查詢 SELECT NAME FROM STAFF WHERE ID = 5 返回一個空的結果集。如果提供一個有效的 ID(比如 10),那么這個存儲過程將返回一個名稱(在本例中是 Sanders)。


    清單 16. SQL4302 示例:db2diag.log 中的相關條目
    																				
    
       
    
    2005-10-02-21.51.36.325000-240 I79282H396         LEVEL: Warning
    
    PID     : 2140                 TID  : 2684        PROC : db2fmp.exe
    
    INSTANCE: DB2                  NODE : 000
    
    FUNCTION: DB2 UDB, BSU Java support, sqlejCallJavaRoutine_dll, probe:315
    
    MESSAGE : Exception thrown during routine invocation:
    
    DATA #1 : Hexdump, 4 bytes
    
    0x01ACF5EC : D480 5501                                  ..U.
    
    
    
    2005-10-02-21.51.36.335000-240 E79680H375         LEVEL: Warning
    
    PID     : 2140                 TID  : 2684        PROC : db2fmp.exe
    
    INSTANCE: DB2                  NODE : 000
    
    FUNCTION: DB2 UDB, BSU Java support, sqlejLogException, probe:10
    
    MESSAGE : ADM10000W  A Java exception has been caught.  The Java stack 
    
              traceback has been written to the db2diag.log.
    
    
    
    2005-10-02-21.51.36.345000-240 I80057H475         LEVEL: Warning
    
    PID     : 2140                 TID  : 2684        PROC : db2fmp.exe
    
    INSTANCE: DB2                  NODE : 000
    
    FUNCTION: DB2 UDB, BSU Java support, sqlejLogException, probe:10
    
    DATA #1 : String, 112 bytes
    
    java.sql.SQLException: SQL0100 : NO DATA FOUND, QUERY RETURNS EMPTY 
    
      RESULT SET at Query.query(Query.java:22)
    
    DATA #2 : Hexdump, 4 bytes
    
    0x01ACF424 : 0000 0000                                  ....
    
    
    
    2005-10-02-21.51.36.355000-240 I80534H384         LEVEL: Warning
    
    PID     : 2140                 TID  : 2684        PROC : db2fmp.exe
    
    INSTANCE: DB2                  NODE : 000
    
    FUNCTION: DB2 UDB, routine_infrastructure, sqlerJavaCallRoutine, probe:30
    
    MESSAGE : Error from DB2ER CallUDF.  RC:
    
    DATA #1 : Hexdump, 4 bytes
    
    0x01ACF97C : 32EF FFFF                                  2...
    
    
    
    2005-10-02-21.51.36.365000-240 I80920H959         LEVEL: Error
    
    PID     : 3632                 TID  : 2840        PROC : db2bp.exe
    
    INSTANCE: DB2                  NODE : 000
    
    APPID   : *LOCAL.DB2.051003014530
    
    FUNCTION: DB2 UDB, oper system services, sqlofica, probe:10
    
    DATA #1 : Hexdump, 136 bytes
    
    0x0012FC90 : 5351 4C43 4120 2020 8800 0000 32EF FFFF    SQLCA   ....2...
    
    0x0012FCA0 : 4600 4357 594C 4157 2E51 5545 5259 FF51    F.CWYLAW.QUERY.Q
    
    0x0012FCB0 : 5545 5259 FF53 514C 3031 3030 203A 204E    UERY.SQL0100 : N
    
    0x0012FCC0 : 4F20 4441 5441 2046 4F55 4E44 2C20 5155    O DATA FOUND, QU
    
    0x0012FCD0 : 4552 5920 5245 5455 524E 5320 454D 5054    ERY RETURNS EMPT
    
    0x0012FCE0 : 5920 5245 5355 4C54 5351 4C45 4A45 5854    Y RESULTSQLEJEXT
    
    0x0012FCF0 : 0000 0000 0000 0000 0000 0000 0000 0000    ................
    
    0x0012FD00 : 0000 0000 0000 0000 2020 2020 2020 2020    ........        
    
    0x0012FD10 : 2020 2033 3835 3031                           38501
    																		

    SQL4304 RC=1


    清單 17. SQL4304 rc=1 示例:AIX 上的 SQL4304RC1.java
    																				
    
    
    
    $ javac SQL4304RC1.java
    
    
    
    $ cp SQL4304RC1.class ~/sqllib/function
    
    
    
    $ db2 -tvf CreateSP_wrong.ddl
    
    CREATE PROCEDURE SQL4304RC1 (IN INPUT int)
    
    SPECIFIC SQL4304RC1
    
    DYNAMIC RESULT SETS 1
    
    DETERMINISTIC
    
    LANGUAGE JAVA
    
    PARAMETER STYLE DB2GENERAL
    
    NO DBINFO
    
    FENCED
    
    THREADSAFE
    
    MODIFIES SQL DATA
    
    PROGRAM TYPE SUB
    
    EXTERNAL NAME 'SQ4304RC1!abend'
    
    
    
    DB20000I  The SQL command completed successfully.
    
    
    
    
    
    $ db2 "call SQL4304RC1(3)"
    
    SQL4304N  Java stored procedure or user-defined function "SHAKEBS.SQL4304RC1",
    
    specific name "SQL4304RC1" could not load Java class "SQ4304RC1", reason code
    
    "1".  SQLSTATE=42724
    																		

    這個操作失敗并且顯示 SQL4304 rc=1 錯誤消息。為什么呢?注意,EXTERNAL NAME 子句中的類名拼寫錯了(它應該是 SQL4304RC1!abend,缺少了 “L”)。要糾正這個錯誤,應該刪除這個過程,并且在 EXTERNAL NAME 子句中采用正確的拼寫來重新創建它。


    清單 18. SQL4304 rc=1 示例:糾正 SQL4304 rc=1 錯誤
    																				
    
    
    
    $ db2 drop procedure SQL4304RC1
    
    DB20000I  The SQL command completed successfully.
    
    
    
    $ db2 -tvf CreateSP.ddl
    
    CREATE PROCEDURE SQL4304RC1 (IN INPUT int)
    
    SPECIFIC SQL4304RC1
    
    DYNAMIC RESULT SETS 1
    
    DETERMINISTIC
    
    LANGUAGE JAVA
    
    PARAMETER STYLE DB2GENERAL
    
    NO DBINFO
    
    FENCED
    
    THREADSAFE
    
    MODIFIES SQL DATA
    
    PROGRAM TYPE SUB
    
    EXTERNAL NAME 'SQL4304RC1!abend'
    
    
    
    DB20000I  The SQL command completed successfully.
    
    
    
    
    
    $ db2 "call SQL4304RC1(3)"
    
    
    
      Result set 1
    
      --------------
    
    
    
      ID     NAME      DEPT   JOB   YEARS  SALARY    COMM
    
      ------ --------- ------ ----- ------ --------- ---------
    
         180 Abrahams      38 Clerk      3  12009.75    236.50
    
         230 Lundquist     51 Clerk      3  13369.80    189.65
    
    
    
      2 record(s) selected.
    
    
    
      Return Status = 0
    																		

    SQL4304 RC=2


    清單 19. SQL4304 rc=2 示例:AIX 上的 SQL4304RC2.java
    																				
    
    
    
    $ javac SQL4304RC2.java
    
    
    
    $ cp SQL4304RC2.class ~/sqllib/function
    
    
    
    $ db2 -tvf CreateSP_wrong.ddl
    
    CREATE PROCEDURE SQL4304RC2 (IN INPUT int)
    
    SPECIFIC SQL4304RC2
    
    DYNAMIC RESULT SETS 1
    
    DETERMINISTIC
    
    LANGUAGE JAVA
    
    PARAMETER STYLE DB2GENERAL
    
    NO DBINFO
    
    FENCED
    
    THREADSAFE
    
    MODIFIES SQL DATA
    
    PROGRAM TYPE SUB
    
    EXTERNAL NAME 'SQL4304RC2!abend'
    
    
    
    DB20000I  The SQL command completed successfully.
    
    
    
    $ db2 "call SQL4304RC2(3)"
    
    SQL4304N  Java stored procedure or user-defined function "SHAKEBS.SQL4304RC2",
    
    specific name "SQL4304RC2" could not load Java class "SQL4304RC2", reason code
    
    "2".  SQLSTATE=42724
    																		

    這個操作失敗并且顯示 SQL4304 rc=2 錯誤消息。為什么呢?因為 PARAMETER STYLE 是 DB2GENERAL,所以需要確保 Java 源代碼擴展 COM.ibm.db2.app.StoredProc。為了糾正這個問題,將 extends COM.ibm.db2.app.StoredProc 添加到存儲過程類名的末尾。


    清單 20. SQL4304 rc=2 示例:SQL4304RC2.java
    																				
    
    
    
    1    //The simplest JAVA SP
    
    2    import java.sql.*;
    
    3    import COM.ibm.db2.app.*;
    
    4     
    
    5    public class SQL4304RC2 extends COM.ibm.db2.app.StoredProc
    
    6    { 
    
    7      public void abend  (int input) throws SQLException,Exception
    
    8      {  
    
    9        int errorCode;
    
    10   
    
    11       try
    
    12       {
    
    13         // get caller's connection to the database
    
    14         Connection con = DriverManager.getConnection("jdbc:default:connection");
    
    15     
    
    16         String query = "SELECT * FROM STAFF where YEARS = ?";
    
    17
    
    18         PreparedStatement pstmt = con.prepareStatement(query);
    
    19         ResultSet rs = null;
    
    20         pstmt.setInt(1, input);
    
    21         rs = pstmt.executeQuery();
    
    22    
    
    23       } 
    
    24       catch (SQLException sqle)
    
    25       {
    
    26         errorCode = sqle.getErrorCode();
    
    27         throw new SQLException( errorCode   " FAILED - "   sqle.getMessage()); 
    
    28       }  
    
    29     }
    
    30   }
    																		

    代碼中的第 5 行現在正確地擴展類。重新對代碼進行編譯,然后替換 sqllib/function 中的 .class 文件,并且重新執行存儲過程。

    注意:導致 SQL4304 rc=2 錯誤消息的另一個常見錯誤是,存儲過程的主方法被聲明為 “public static” 方法。PARAMETER STYLE DB2GENERAL 過程不能聲明為 “static” 方法,像以上代碼的第 7 行那樣進行聲明才是正確的。


    清單 21. SQL4304 rc=2 示例:糾正 SQL4304 rc=2 錯誤
    																				
    
    
    
    $ javac SQL4304RC2.java
    
    
    
    $ cp SQL4304RC2.class ~/sqllib/function
    
    
    
    $ db2 "call SQL4304RC2(3)"
    
    
    
      Result set 1
    
      --------------
    
    
    
      ID     NAME      DEPT   JOB   YEARS  SALARY    COMM
    
      ------ --------- ------ ----- ------ --------- ---------
    
         180 Abrahams      38 Clerk      3  12009.75    236.50
    
         230 Lundquist     51 Clerk      3  13369.80    189.65
    
    
    
      2 record(s) selected.
    
    
    
      Return Status = 0
    																		

    SQL4306


    清單 22. SQL4306 示例:INSERT.sqlj
    																				
    
         
    
    D:\>sqlj INSERT.sqlj
    
       
    
    D:\>db2sqljcustomize -user cwylaw -password xxxxxxxxx -url 
    
       jdbc:db2://claw.torolab.ibm.com:50000/sample INSERT_SJProfile0
    
    [ibm][db2][jcc][sqlj]
    
    [ibm][db2][jcc][sqlj] Begin Customization
    
    [ibm][db2][jcc][sqlj] Loading profile: INSERT_SJProfile0
    
    [ibm][db2][jcc][sqlj] Customization complete for profile 
    
        INSERT_SJProfile0.ser
    
    [ibm][db2][jcc][sqlj] Begin Bind
    
    [ibm][db2][jcc][sqlj] Loading profile: INSERT_SJProfile0
    
    
    
    [ibm][db2][jcc][sqlj] Driver defaults(user may override): BLOCKING ALL 
    
        VALIDATE BIND STATICREADONLY YES
    
    [ibm][db2][jcc][sqlj] Fixed driver options: DATETIME ISO DYNAMICRULES BIND
    
    [ibm][db2][jcc][sqlj] Binding package INSERT01 at isolation level UR
    
    [ibm][db2][jcc][sqlj] Binding package INSERT02 at isolation level CS
    
    [ibm][db2][jcc][sqlj] Binding package INSERT03 at isolation level RS
    
    [ibm][db2][jcc][sqlj] Binding package INSERT04 at isolation level RR
    
    [ibm][db2][jcc][sqlj] Bind complete for INSERT_SJProfile0
    
    
    
    D:\>jar -cvf INSERT.jar *.class *.ser
    
    added manifest
    
    adding: INSERT.class(in = 1192) (out= 684)(deflated 42%)
    
    
    
    D:\>db2 call sqlj.install_jar("file:///D:\INSERT.jar", 
    
    'INSERTJAR')
    
    DB20000I  The CALL command completed successfully.
    
    
    
    D:\>db2 -tvf Create.ddl
    
    CREATE PROCEDURE INSERT (IN INPUT CHAR(3))
    
    SPECIFIC INSERT
    
    DYNAMIC RESULT SETS 0
    
    DETERMINISTIC
    
    LANGUAGE JAVA
    
    PARAMETER STYLE JAVA
    
    NO DBINFO
    
    FENCED
    
    THREADSAFE
    
    MODIFIES SQL DATA
    
    PROGRAM TYPE SUB
    
    EXTERNAL NAME 'INSERT.INSERT'
    
    
    
    DB20000I  The SQL command completed successfully.
    
    
    
    D:\>db2 call INSERT('abc')
    
    SQL4306N  Java stored procedure or user-defined function "CWYLAW.INSERT",
    
    specific name "INSERT" could not call Java method "INSERT", 
    
    signature "(Ljava/lang/String;)V".  SQLSTATE=42724
    																		

    為什么會產生這個 SQL4306 錯誤?請看看源代碼和 CREATE PROCEDURE 語句。注意,在 Java 代碼中,方法被聲明為:public static void iNSERT (String input)

    注意小寫字母‘i’。


    清單 23. SQL4306 示例:Windows 上的 INSERT.sqlj
    																				
    
    
    
    //The simplest SQLJ SP
    
    import java.sql.*;
    
    import sqlj.runtime.*; 
    
    import sqlj.runtime.ref.*; 
    
     
    
    public class INSERT 
    
    {
    
      public static void iNSERT (String input) throws SQLException, Exception
    
     
    
        { 
    
        	#sql { INSERT INTO CWYLAW.StoreData (c) VALUES (:input) }; 
    
        }  
    
    }
    																		


    清單 24. SQL4306 示例:INSERT 過程所需的 StoreData 表的 CREATE TABLE 語句
    																				
    
    
    
    CREATE TABLE StoreData (c char(3));
    																		

    但是,在 CREATE PROCEDURE 語句中,EXTERNAL NAME 被聲明為 EXTERNAL NAME 'INSERT.INSERT'。注意大寫字母‘I’。所以,出現 SQL4306 錯誤的原因是源代碼中的 Java 方法名與 CREATE PROCEDURE 語句中的 EXTERNAL NAME 不匹配。要糾正這個問題,就要確保 Java 方法與 CREATE PROCEDURE 語句中的 EXTERNAL NAME 子句精確匹配。在這個例子中,我們選擇修改 CREATE PROCEDURE 語句而不是修改源代碼。


    清單 25. SQL4306 示例:INSERT 存儲過程的正確的 CREATE PROCEDURE 語句
    																				
    
    
    
    CREATE PROCEDURE INSERT (IN INPUT CHAR(3))
    
    SPECIFIC INSERT
    
    DYNAMIC RESULT SETS 0
    
    DETERMINISTIC
    
    LANGUAGE JAVA
    
    PARAMETER STYLE JAVA
    
    NO DBINFO
    
    FENCED
    
    THREADSAFE
    
    MODIFIES SQL DATA
    
    PROGRAM TYPE SUB
    
    EXTERNAL NAME 'INSERT.iNSERT'
    
    ;
    																		

    現在,INSERT 過程能夠成功運行了。


    清單 26. 運行 INSERT 過程
    																				
    
    D:\>db2 drop procedure INSERT
    
    DB20000I  The SQL command completed successfully.
    
    
    
    D:\>db2 call sqlj.remove_jar('INSERTJAR')
    
    DB20000I  The CALL command completed successfully.
    
    
    
    D:\>db2 call sqlj.install_jar("file:///D:\INSERT.jar", 'INSERTJAR')
    
    DB20000I  The CALL command completed successfully.
    
    
    
    D:\>db2 -tvf Create.ddl
    
    CREATE PROCEDURE INSERT (IN INPUT CHAR(3))
    
    SPECIFIC INSERT
    
    DYNAMIC RESULT SETS 0
    
    DETERMINISTIC
    
    LANGUAGE JAVA
    
    PARAMETER STYLE JAVA
    
    NO DBINFO
    
    FENCED
    
    THREADSAFE
    
    MODIFIES SQL DATA
    
    PROGRAM TYPE SUB
    
    EXTERNAL NAME 'INSERT.iNSERT'
    
    
    
    DB20000I  The SQL command completed successfully.
    
    D:\>db2 call INSERT('abc')
    
    
    
      Return Status = 0
    
      
    
    D:\>db2 select * from StoreData
    
    
    
    C
    
    ---
    
    abc
    
    
    
      1 record(s) selected.
    																		

    還應該花點兒時間看看類型簽名的 JVM 表示,因為這可以幫助您在遇到 SQL4306 錯誤時識別出問題。SQL4306 錯誤的另一個常見原因是過程的參數與 Java 方法定義不匹配。在這個例子中,SQL4306 錯誤的末尾包含一個含義有點兒模糊的錯誤符號:


    清單 27. SQL4306 錯誤顯示了 JVM 返回的 Java 類型
    																				
    
    
    
    SQL4306N  Java stored procedure or user-defined function "CWYLAW.INSERT",
    
    specific name "INSERT" could not call Java method "INSERT", signature
    
    "(Ljava/lang/String;)V".  SQLSTATE=42724
    																		

    (Ljava/lang/String;)V 實際上是 JVM 返回的 Java 類型簽名。

    表 2. Java VM 類型簽名
    類型簽名 Java 類型
    Z boolean
    B byte
    C char
    S short
    I int
    J long
    F float
    D double
    L fully-qualified-class ; fully-qualified-class
    [ type type[]
    ( arg-types ) ret-type method type

    所以這個錯誤消息指出,DB2 試圖調用 Java 存儲過程 INSERT,這個過程的 Java VM 類型簽名是 (Ljava/lang/String;)V,其中 fully-qualified-classjava/lang/String(即,輸入參數是類型 String),返回類型是 V,代表類型 void。這精確地匹配 Java 方法定義:

    public static void iNSERT (String input)

    現在,已經證實 Java VM 簽名是正確的,所以確定了問題

    posted on 2006-07-21 10:03 MyJavaWorld 閱讀(5620) 評論(0)  編輯  收藏

    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 亚洲熟妇无码另类久久久| 亚洲高清美女一区二区三区| A国产一区二区免费入口| 色婷婷亚洲十月十月色天| 成年网站免费视频A在线双飞| 亚洲一区二区三区国产精华液| 免费一级特黄特色大片在线观看| 在线观看免费视频一区| 亚洲综合丁香婷婷六月香| 亚洲综合精品网站在线观看| 1000部免费啪啪十八未年禁止观看 | 亚洲爱情岛论坛永久| 操美女视频免费网站| 成人av片无码免费天天看| 国产成人精品亚洲2020| 中文字幕亚洲无线码a| 亚洲一区在线免费观看| 国产免费区在线观看十分钟| 99久久国产亚洲综合精品| 亚洲一区精品无码| 午夜毛片不卡高清免费| 日本高清免费观看| 黄色网址大全免费| 亚洲国产成人精品无码一区二区| 久久99亚洲综合精品首页| 成人片黄网站A毛片免费| 免费观看在线禁片| 四虎精品成人免费视频| 亚洲AV男人的天堂在线观看| 亚洲精品国产精品乱码不卡√| 日本一区二区三区日本免费| 5555在线播放免费播放| a毛片在线免费观看| 日韩大片在线永久免费观看网站 | 久久久亚洲AV波多野结衣 | 亚洲无圣光一区二区| 亚洲精品无码久久久久去q| 国产成人涩涩涩视频在线观看免费 | 一级特黄a大片免费| 亚洲精品精华液一区二区| 亚洲午夜电影一区二区三区|