當前位置:首頁 » 存儲配置 » db2存儲過程調用java

db2存儲過程調用java

發布時間: 2024-09-18 17:12:22

『壹』 如何在DB2中執行存儲過程

1、db2 create database 資料庫名 <-- 創建資料庫 2、db2 connect to 資料庫名 user 用戶名 using 用戶密碼 <-- 連接資料庫 3、db2 -tvf otpdb_v3_db2.sql <-- 為新建資料庫建立表結構 4、db2 -td@ -f 存儲過程文件絕對路徑 <-- 導入存儲過程,無錯誤會提示成功 4、調用存儲過程: Windows 下:db2 call 存儲過程名(參數1,參數2) AIX 下:db2 <-- 要先進入DB2,方可調用存儲過程或執行SQL語句 db2=>call 存儲過程名(參數1,參數2) 5、驗證插入數據是否成功 Windows 下:db2 select count(*) from FTOTP_USERINFO AIX 下:db2 <-- 要先進入DB2,方可調用存儲過程或執行SQL語句 db2=>select count(*) from FTOTP_USERINFO Windows 下:db2 select count(*) from FTOTP_TOKENINFO AIX 下:db2 <-- 要先進入DB2,方可調用存儲過程或執行SQL語句 db2=>select count(*) from FTOTP_TOKENINFO 6、db2 SELECT TOKEN, PUBKEY FROM FTOTP_TOKENINFO FETCH FIRST 10000 ROWS ONLY > 要保存文件的絕對全路徑 <-- 從 DB2 中導出前一萬條記錄 windows - e.g. db2 SELECT TOKEN, PUBKEY FROM FTOTP_TOKENINFO FETCH FIRST 10000 ROWS ONLY > c:\abc.txt AIX - e.g. db2 SELECT TOKEN, PUBKEY FROM FTOTP_TOKENINFO FETCH FIRST 10000 ROWS ONLY > c:\abc.txt <-- 注意:不能先進入DB2,執行查詢與導出命令組合 7、db2 drop procere 存儲過程名 <-- 刪除存儲過程 8、db2 drop database 資料庫名 <-- 刪除指定名稱的資料庫 注,如果刪除時提示有應用程序連接到這個資料庫上,可以用如下命令斷開所有應用程序的連接: db2 force application all <-- 斷開所有應用程序的連接

『貳』 怎麼使用java連接資料庫

1、首先我們先建好資料庫,然後建立好程序的目錄,因為是適用於初學者的,所以就建立一個簡單的java project,如圖。

『叄』 data studio中的存儲過程怎麼寫。使用datastudio

簡介
IBM Data Studio Developer V1.2 包含一個 Unified Debugger 客戶機,支持調試 SQL 存儲過程。如果您熟悉用 Eclipse 平台調試應用程序,會發現調試 DB2 SQL 過程的步驟是很相似的。在本文中,介紹如何使用 IBM Data Studio Developer V1.2 中的調試特性調試一個示例 DB2 for z/OS SQL 存儲過程。本文中的許多步驟也可以應用於在 DB2 for Linux®, UNIX®, and Windows® 和 DB2 for i 上創建的 SQL 存儲過程。本文中使用的示例存儲過程專門針對 DB2 for z/OS v9。
要想從本文獲得最大收益,您應該熟悉使用 IBM Data Studio Developer 創建資料庫連接以及操作表和存儲過程等資料庫對象。熟悉 IBM Data Studio Developer 的好方法是下載試用版並閱讀它的教程系列(見 參考資料)。
了解不同 DB2 版本中的調試器技術
DB2 for z/OS 有兩種 IBM 調試器技術:
老式技術稱為 SQL Debugger,支持 DB2 for z/OS V8(包含與 LUW V8 FP7 同時發布的 V8 PTF UK03933)。它只為外部 SQL 存儲過程提供調試器支持。
Unified Debugger 是最新的調試器技術,支持 DB2 for z/OS V8(包含與 DB2 for Linux, UNIX, and Windows V9 FP2 同時發布的 PTF UK25860)和 DB2 for z/OS V9。對於 DB2 for z/OS V8,可以使用 Unified Debugger 調試外部 SQL 存儲過程。但是,對於 DB2 for z/OS V9,它支持調試 Java 存儲過程、原生 SQL 過程和外部 SQL 存儲過程。
這兩種技術之間的主要差異是,Unified Debugger 同時支持調試 Java 和 SQL 過程,而且繼續支持調試嵌套的過程調用。本文討論 Unified Debugger。
准備示例表
本文中創建的存儲過程是用原生 SQL 編寫的,以商品 ID 作為輸入,使用 PRODUCT 表中存儲的成本、送貨費用和客戶付款信息計算商品的利潤。存儲過程的輸出稱為 PROFIT,這一數據被存儲回 PRODUCT 表。
清單 1 給出創建和填充 PRODUCT 表所需的 DDL。如果希望檢驗過程中的 SQL 語句,需要先運行這個 DDL。

清單 1. 創建示例 proct 表的 DDL

CREATE TABLE ADMF001.PRODUCT
(
ITEM VARCHAR(6) NOT NULL,
COST DECIMAL(8,2),
SHIPPING DECIMAL(8,2),
PAYMENT DECIMAL(8,2),
PROFIT DECIMAL(8,2)
);

INSERT INTO ADMF001.PRODUCT (ITEM, COST, SHIPPING, PAYMENT)
VALUES ('001', 100.00, 19.99, 150);

INSERT INTO ADMF001.PRODUCT (ITEM, COST, SHIPPING, PAYMENT)
VALUES ('002',80, 8.99, 99.99);

創建和部署存儲過程
在本節中,使用 Stored Procere 向導生成示例存儲過程的簡單版本。需要修改生成的存儲過程,添加計算利潤的邏輯。然後,學習如何指定在啟用調試選項的情況下部署存儲過程。如果不這樣做,就無法調試存儲過程。
創建過程
調試現有的存儲過程
如果在伺服器上有任何現有的 SQL 存儲過程,那麼可以把它從 Database Explorer 拖入數據開發項目中,然後進行調試。但是,需要確保存儲過程為調試做好了准備,這意味著存儲過程在部署時要啟用調試選項。
如果存儲過程在部署時沒有 啟用調試選項,就無法調試它;必須選擇 Enable debugging 並再次部署它。
按照以下步驟創建名為 PROFITUPDATE 的示例存儲過程:
首先,在 Data Studio Developer 中使用 DB2 for z/OS 資料庫連接創建一個新的數據開發項目。選擇 File > New > Data Development Project。向導要求指定一個資料庫連接。如果還沒有資料庫連接,那麼可以使用資料庫連接向導創建一個 DB2 for z/OS 資料庫連接。

圖 1. 選擇資料庫連接

接下來,使用 New Stored Procere 向導創建一個 SQL 存儲過程。可以右鍵單擊剛才創建的項目,選擇 New > Stored Procere(見圖 2),從而啟動 New Stored Procere 向導。把存儲過程命名為 PROFITUPDATE 並指定原生 SQL 作為它的語言。

圖 2. 創建新的 SQL 存儲過程

在 SQL Statements 頁面上,在 Statement details 框中添加清單 2 所示的 SQL 語句。注意,變數名前面有一個冒號 (:),這把它定義為主機變數。

清單 2. PROFITUPDATE 存儲過程的 SQL 語句

SELECT COST, SHIPPING, PAYMENT FROM PRODUCT
WHERE ITEM = :itemID;

圖 3. SQL Statements 頁面

單擊 Validate 按鈕檢查 SQL 語法。如果語法有錯誤,它會在把語句寫入過程之前指出錯誤。另外,它還幫助格式化 SQL 語句。圖 3 給出檢查之後語句的樣子。單擊 Next。
在 Parameters 頁面上(圖 4),會注意到已經基於主機變數 :itemID 創建了輸入變數 itemID。在這個頁面上,可以修改現有的參數、添加新參數和刪除不再需要的參數。

圖 4. Parameters 頁面

現在,必須通過單擊 Add… 按鈕添加第二個參數(輸出參數)。這個參數名為 itemProfit,模式為 OUT。類型為 Decimal (8,2),見圖 5。單擊 OK。

圖 5. 添加參數

在向導的 Deploy Options 頁面上,可以通過選中 Enable debugging 復選框啟用調試,見圖 6。單擊 Finish。

圖 6. 確保選中 Enable debugging 復選框

現在,應該會在圖 6-1 所示的編輯器中打開創建的存儲過程。

圖 6-1. 生成的過程

在查看源代碼時,會注意到它不包含計算利潤的邏輯。需要修改存儲過程的過程體,添加這種邏輯。為了節省時間,可以復制並粘貼清單 3 所示的示例過程體。

清單 3. 計算利潤的存儲過程

CREATE PROCEDURE PROFITUPDATE ( IN itemID VARCHAR(6),
OUT itemProfit DECIMAL(8, 2) )
VERSION VERSION1
ISOLATION LEVEL CS
LANGUAGE SQL
ALLOW DEBUG MODE
WLM ENVIRONMENT FOR DEBUG MODE WLMENV1
QUALIFIER ADMF001
COMMIT ON RETURN YES
------------------------------------------------------------------------
-- SQL Stored Procere
-- itemID
-- itemProfit
------------------------------------------------------------------------
P1: BEGIN
-- Declare variables

DECLARE itemPayment DECIMAL(8,2) DEFAULT 0.0;
DECLARE total_cost DECIMAL(8,2) DEFAULT 0.0;

P2: BEGIN
DECLARE itemCost DECIMAL(8,2) DEFAULT 0.0;
DECLARE itemShippingFee DECIMAL(8,2) DEFAULT 0.0;

-- Declare cursor
DECLARE cursor1 CURSOR FOR
SELECT COST, SHIPPING, PAYMENT FROM PRODUCT
WHERE ITEM = itemID;

OPEN cursor1;

FETCH cursor1 INTO itemCost, itemShippingFee, itemPayment;
SET total_cost = itemCost + itemShippingFee;

END P2;

SET itemProfit = itemPayment - total_cost;
UPDATE PRODUCT SET PROFIT = itemProfit
WHERE ITEM = itemID;
END P1

單擊 Save 保存存儲過程。現在要部署存儲過程了。
部署存儲過程
為了部署存儲過程,在 Data Project Explorer 中右鍵單擊過程並選擇 Deploy。因為前面在創建這個過程時啟用了調試,它在部署時會啟用調試選項。如果還沒有啟用調試選項,仍然可以在部署向導的 Routine Options 部分中選中 Enable debugging 復選框(圖 7)。

圖 7. Deploy Routines 向導中的 Enable debugging 選項

設置調試器會話管理程序
在調試存儲過程之前,了解調試器框架會有幫助。Unified Debugger 有三個組件:伺服器、客戶機和會話管理程序,見圖 8。在這個框架中,客戶機與會話管理程序通信,會話管理程序與伺服器通信,從而交換調試信息和請求。

圖 8. Unified Debugger 框架

可以看出會話管理程序非常重要,它是一個中間件,負責通過 TCP/IP 連接協調客戶機和伺服器之間的通信。在使用調試器之前,需要在網路上某個地方(客戶機、伺服器或其他地方)啟動會話管理程序進程。如果還沒有正確地設置它,那麼由於會話管理程序不可用,在使用 IBM Data Studio Developer 時會遇到問題(圖 9),因此無法使用 Unified Debugger。

圖 9. 會話管理程序不可用

如果在環境中的伺服器上運行會話管理程序,就不需要在客戶端做任何設置。但是,伺服器端設置很復雜(尤其是在 z/OS 環境中),所以本文只關注在客戶端上使用調試器,伺服器端設置留到另一篇文章中討論。同時,建議通過 參考資料 中列出的 Redbook 了解為存儲過程調試設置 DB2 for z/OS 環境的信息。
如果會話管理程序不在本地運行,應該怎麼辦?
如果會話管理程序在網路上的某個地方運行,那麼仍然可以使用本節描述的步驟,但是需要找到駐留它的伺服器上的 db2dbgm.bat。
使用會話管理程序的最簡便方法是在客戶機上運行它,然後配置 debugger Preferences 頁面。在客戶機上運行會話管理程序的步驟如下:
找到 Data Studio Developer v1.2 附帶的會話管理程序。這個文件名為 db2dbgm.bat。它位於以下目錄中:
[DS install directory] \dsdev\bin

在命令提示窗口中執行 db2dbgm.bat。它會提供一個主機 IP 地址和埠號,您應該記住它們。它的設置還包括超時信息。圖 10 所示的 db2dbgm.bat 示例輸出表明,如果會話管理程序空閑了 50 分鍾,它就會超時。(指定零值表示沒有會話管理程序超時)。可以通過編輯 db2dbgm.bat 修改空閑時間和埠號。

圖 10. 啟動會話管理程序並獲得 IP 地址和埠號

既然已經得到了正在運行的會話管理程序的 IP 地址和埠號,就需要在調試器首選項的會話管理程序部分中輸入這些信息:
選擇 Window>Preferences…。
在 Run/Debug > DB2 Stored Procere Debugger 下面找到 debugger preferences 頁面。
單擊 debugger preferences 頁面上的 Use already running session manager 單選按鈕,輸入前面記下的 IP 地址和埠號。

圖 11. 在首選項中指定會話管理程序的 IP 地址和埠號

注意:不要關閉會話管理程序窗口,因為這會結束會話管理程序會話。因此,應該繼續調試並讓會話管理程序窗口在後台運行。
設置其他調試器首選項
除了會話管理程序之外,還可以在開始調試之前配置其他調試器首選項。本節簡要介紹其中兩個選項,見圖 12。

圖 12. DB2 存儲過程調試器首選項

Inactivity setting:在讓調試器停在一個斷點上時,如果不執行任何進一步的調試操作,就認為調試是空閑的。為了避免無限期地持有伺服器資源,調試器假設在經過指定的無活動時間段之後應該結束調試,讓過程自動地運行完。可以在 Debugger preference 頁面上指定調試器的無活動時間長度。默認值是 300 秒。
Error trace setting:為了幫助判斷問題,IBM 服務代表可能要求您在伺服器上啟用診斷跟蹤。值 2 在 DB2 伺服器上啟用完整的診斷跟蹤。除非 IBM 服務代表明確要求啟用伺服器診斷跟蹤,否則應該保持這個設置為 0(零)。
可選:在進行調試之前設置運行設置
最後,作為開始調試之前的最後一個可選步驟,指定應用於本次運行的設置,包括:
指定在調試之前或之後運行的某些 SQL 語句(對這些語句不進行調試)
設置一個輸入參數值
指定是否把更改提交到資料庫
為 DB2 for z/OS 連接設置集合 ID
示例存儲過程在最後更新 PRODUCT 表。為了檢查更新,可以用一個運行後語句顯示對 PRODUCT 表執行 SELECT 語句的結果。本節介紹具體做法。
在 Data Project Explorer 中右鍵單擊存儲過程並選擇 Run Settings,打開 Run Settings 對話框,見圖 13。

圖 13. Run settings 菜單

Run settings 窗口有多個選項卡。選擇 After Run 選項卡並輸入 select * from PRODUCT 語句,見圖 14。

圖 14. Run settings 對話框窗口

在運行或調試存儲過程之後,會執行這個 SQL 語句。利潤更新的結果會顯示在輸出視圖中。
注意:在 Run Settings 對話框中,還可以在 Parameter Values 選項卡中指定參數值。但是,如果不在這里指定,在調試過程中仍然有機會指定參數值。
回頁首
開始調試
現在,已經完成了所有設置活動,可以開始調試存儲過程了。
開始調試的方法是在 Data Project Explorer 中右鍵單擊存儲過程名,然後選擇 Debug…,見圖 15。

圖 15. 在 Data Project Explorer 中從過程啟動調試器

調試器首先啟動標準的 Eclipse 調試配置頁面,見圖 16。所有配置項都預先設置了。單擊 Debug 繼續。

圖 16. 調試配置頁面

因為示例存儲過程有一個輸入變數,所以調試器會打開 Specify Parameter Values 對話框,可以在其中輸入參數值。如果前面在 Run Settings 對話框中輸入了參數值,這個值會再次顯示出來,可以檢查或修改它。

圖 17. Specify Parameter Values 對話框

調試在 Debug 透視圖中進行。下面的窗口要求您確認切換到 Debug 透視圖。單擊 Yes 繼續。還可以單擊復選框讓它記住您的決定,這樣就不會再提示確認。

圖 18. 切換到 Debug 透視圖

現在,調試器開始工作了。在存儲過程邏輯前麵包含 PROCEDURE 關鍵字的行上總是設置一個隱含的斷點。當前位置用一個箭頭突出顯示。可以讓過程停在任何執行行上進行調試。如果設置了任何斷點,還可以一直運行到下一個有效斷點。

圖 19. 調試器停在第一行上

回頁首
調試器透視圖、視圖和操作
Eclipse Debug 透視圖(圖 20)提供幾個幫助調試存儲過程的視圖。本節介紹這些視圖。
Debug 視圖
Variables 視圖
Breakpoints 視圖
Data Output 視圖

圖 20. Debug 透視圖概況

Debug 視圖
Debug 視圖顯示當前的調用堆棧。它提供存儲過程名和當前行號。在 Debug 視圖中,可以通過圖 21 所示的工具欄執行不同的操作,包括 Step Into、Step Over、Step Return、Resume 和 Terminate:

圖 21. Debug 視圖及其操作

使用 Step Over 逐行調試過程。

使用 Step Into 調試嵌套的過程。如果沒有嵌套的過程,那麼它的作用與 Step Over 相同。

Step Return 幫助從嵌套的過程返回。如果當前不在嵌套的過程中,那麼 Step Return 運行完整個過程,忽略所有斷點。

當停在某一行上時,可以使用 Resume 執行到下一個有效的斷點。如果後面沒有有效的斷點,就一直運行到過程結束並停止調試。

使用 Terminate 在任何時候停止調試。

最後,可以通過單擊這個圖標刪除所有終止的運行:

關於嵌套過程的提示:如果有嵌套的過程調用,Debug 視圖可以提供外層過程和嵌套過程的調試信息,包括每個過程中的當前行號。
圖 22 給出一個調試嵌套的存儲過程的示例,其中的 Procere1 調用 Procere2。在調用 procere2(var1) 的行上,如果選擇 step into 操作,調試器就會進入 Procere2 內部,從第一行開始調試 Procere2。在調用堆棧上可以看到,Procere2 現在出現在 Procere1 上面。調試完 Procere2 之後,調試器回到 Procere1。

圖 22. 調試嵌套的存儲過程

Variables 視圖
Variables 視圖(圖 23)顯示當前可用的變數和參數的當前值。Unified Debugger 還顯示 SQLCODE 和 SQLSTATE 診斷信息。

圖 23. Variables 視圖

在 Variables 視圖中可以:
指定變數修改斷點。
把所有變數值復制並粘貼到其他文件。
根據調試的需要修改變數值。可以雙擊變數值並輸入新值,也可以右鍵單擊變數並從彈出菜單中選擇 Change Value…,見圖 24。

圖 24. 在 Variables 視圖中查看並修改變數

不能修改診斷信息 SQLCODE 或 SQLSTATE 的值,也不能在它們上面設置變數修改斷點。它們不同於一般的變數。
Breakpoints 視圖
Breakpoints 視圖顯示已經為存儲過程設置的所有斷點。Breakpoints 視圖提供標準的斷點管理支持,包括:
啟用/禁用斷點
刪除斷點
導入/導出斷點
Unified Debugger 支持兩種斷點:行斷點和變數修改斷點。在下圖中,Breakpoints 視圖顯示這兩種斷點。

圖 25. Breakpoints 視圖

添加新斷點:在編輯器中雙擊一行右邊的空白邊,就會在這一行上設置行斷點。還可以右鍵單擊編輯器的左邊,然後使用出現的 Add Breakpoint 菜單設置行斷點。

圖 26. Add Breakpoint 菜單

如果在包含有效 SQL 過程執行語句的行上設置了斷點,在調試期間調試器可以停在這一行上。某些源代碼行和 SQL 過程語句不能設置斷點,比如注釋行或游標聲明。另外,每個 SQL 過程語句只有一個為語句定義可中斷點的關鍵字。一般情況下,有效的斷點是 SQL 過程語句的第一個關鍵字。在為跨多個源代碼行的語句設置斷點時要小心。可以通過 Step Over 操作熟悉這些有效斷點位置。

圖 27. 行斷點

可以在 Variables 視圖中設置變數修改斷點。在 Variables 視圖中,右鍵單擊一個變數並選擇 Add Variable Change Breakpoint。調試期間,當變數值改變時,調試器會停在修改變數的行上。

圖 28. 創建變數修改斷點

Data Output 視圖
Data Output 視圖顯示調試完成時過程的結果。結果與正常運行存儲過程時的結果相同。它提供調試操作的狀態信息、運行消息、參數值和運行結果。Data Output 視圖有助於檢查運行存儲過程的結果。如果結果不符合預期,可以重新調試存儲過程。
對於我們的示例存儲過程,第二個商品(item 002)的利潤是 11.00。利潤值顯示在 Data Output 視圖的 Parameters 選項卡中的 OUT 模式參數 itemProfit 中。

圖 29. Data Output 視圖 - 調試操作的結果

還記得在 Run Settings 中如何設置運行後語句嗎?運行後語句的執行結果也顯示在 Data Output 視圖中。如圖 30 所示,Results 選項卡中列出了 PRODUCT 表的內容。表中 item 002 的利潤值是 11.00。

圖 30. Data Output 視圖 – 運行後語句的執行結果

回頁首
需要了解的其他問題
到目前為止,已經了解了如何為調試准備會話管理程序、如何創建存儲過程、如何在啟用調試選項的情況下部署它以及如何通過檢查變數值和結果來調試它。本節討論在 DB2 for z/OS 上進行調試時常常出現的一些情況。
無法找到會話管理程序
正如前面提到的,可以在客戶機、伺服器或網路上的其他地方設置會話管理程序。有時候,即使設置了會話管理程序,IBM Data Studio Developer 仍然報告會話管理程序不可用。
如果遇到這樣的問題,而且您的會話管理程序在伺服器或網路上的其他地方運行,那麼可能是防火牆阻斷了 TCP/IP 連接。另外,有時候是由於 IP 地址不正確。檢查 TCP/IP 連接路徑是否通暢的好方法是從伺服器 ping 會話管理程序的 IP 地址。
超時問題
Unified Debugger 使用兩個 超時設置。一個用於調試客戶機;另一個用於會話管理程序。如果會話管理程序在指定的時間段內沒有為調試會話服務,它就會關閉。要想再次使用會話管理程序,就必須重新啟動它。調試客戶機會釋放一段時間內無活動的調試會話。一定要根據自己的需要調整這兩個設置。
調試器菜單未啟用
有時候,調試器菜單被禁用了。下面兩種情況會導致這個問題:
首先,可能沒有在啟用調試選項的情況下部署存儲過程。可以在編輯器中打開過程,然後檢查是否選中了 Enable Debugging 復選框。
第二,資料庫連接可能不支持調試器。正如前面提到的,對於在帶 PTF UK03933 的 V8 上啟動的 DB2 for z/OS,提供調試器支持。如果連接到 DB2 for z/OS V7,就無法在 Data Studio Developer V1.2 中調試存儲過程。
結束語
IBM Data Studio Developer 為 SQL 存儲過程提供調試特性,允許在 Eclipse 框架中按照與調試 Java 應用程序相似的方式進行調試。本文介紹了如何對 DB2 for z/OS 上的 SQL 存儲過程進行調試,但是許多概念也適用於其他 DB2 伺服器。
致謝
我們衷心感謝 Kathy Zeidenstein、Tina Chen 和其他審閱者為審閱本文提供幫助!

參考資料
學習
通過 RSS feed 請求本系列後續文章的通知。(了解關於 developerWorks 內容的 RSS feed 的更多信息) 。

通過 IBM Data Studio 產品專題,了解 Data Studio 產品和技術相關的資源。

查閱 IBM Data Studio 的 產品頁面,了解這個產品能夠給企業帶來的好處。

Get Started with Data Studio Developer:這個教程概述了 Data Studio Developer。

『肆』 執行存儲過程有多少種方法java

Java執行存儲過程的方法:

簡單的老的JDBC通過CallableStatement類支持存儲過程的調用。該類實際上是PreparedStatement的一個子類。假設有一個poets資料庫。資料庫中有一個設置詩人逝世年齡的存儲過程。下面是對老酒鬼Dylan Thomas(old soak Dylan Thomas,不指定是否有關典故、文化,請批評指正。譯注)進行調用的詳細代碼:

try{
intage=39;
StringpoetName="dylanthomas";
CallableStatementproc=connection.prepareCall("{callset_death_age(?,?)}");
proc.setString(1,poetName);
proc.setInt(2,age);
cs.execute();
}catch(SQLExceptione){//....}

傳給prepareCall方法的字串是存儲過程調用的書寫規范。它指定了存儲過程的名稱,?代表了需要指定的參數。
和JDBC集成是存儲過程的一個很大的便利:為了從應用中調用存儲過程,不需要存根(stub)類或者配置文件,除了你的DBMS的JDBC驅動程序外什麼也不需要。
當這段代碼執行時,資料庫的存儲過程就被調用。我們沒有去獲取結果,因為該存儲過程並不返回結果。執行成功或失敗將通過例外得知。失敗可能意味著調用存儲過程時的失敗(比如提供的一個參數的類型不正確),或者一個應用程序的失敗(比如拋出一個例外指示在poets資料庫中並不存在「Dylan Thomas」)

結合SQL操作與存儲過程

映射Java對象到SQL表中的行相當簡單,但是通常需要執行幾個SQL語句;可能是一個SELECT查找ID,然後一個INSERT插入指定ID的數據。在高度規格化(符合更高的範式,譯注)的資料庫模式中,可能需要多個表的更新,因此需要更多的語句。Java代碼會很快地膨脹,每一個語句的網路開銷也迅速增加。
將這些SQL語句轉移到一個存儲過程中將大大簡化代碼,僅涉及一次網路調用。所有關聯的SQL操作都可以在資料庫內部發生。並且,存儲過程語言,例如PL/SQL,允許使用SQL語法,這比Java代碼更加自然。早期的存儲過程,使用Oracle的PL/SQL語言編寫:

createprocereset_death_age(poetVARCHAR2,poet_ageNUMBER)
poet_idNUMBER;
beginSELECTidINTOpoet_idFROMpoetsWHEREname=poet;
INSERTINTOdeaths(mort_id,age)VALUES(poet_id,poet_age);
endset_death_age;

set_death_age幾乎可以肯定是一個很爛的實現。應該在poets表中添加一列來存儲逝世年齡。Java代碼中並不關心資料庫模式是怎麼實現的,因為它僅調用存儲過程。以後可以改變資料庫模式以提高性能,但是不必修改代碼。
下面是調用上面存儲過程的Java代碼:

publicstaticvoidsetDeathAge(PoetdyingBard,intage)throwsSQLException{
Connectioncon=null;
CallableStatementproc=null;
try{
con=connectionPool.getConnection();
proc=con.prepareCall("{callset_death_age(?,?)}");
proc.setString(1,dyingBard.getName());
proc.setInt(2,age);
proc.execute();
}
finally{
try{proc.close();}
catch(SQLExceptione){}
con.close();
}
}

為了確保可維護性,建議使用像這兒這樣的static方法。這也使得調用存儲過程的代碼集中在一個簡單的模版代碼中。如果用到許多存儲過程,就會發現僅需要拷貝、粘貼就可以創建新的方法。因為代碼的模版化,甚至也可以通過腳本自動生產調用存儲過程的代碼。

Functions

存儲過程可以有返回值,所以CallableStatement類有類似getResultSet這樣的方法來獲取返回值。當存儲過程返回一個值時,必須使用registerOutParameter方法告訴JDBC驅動器該值的SQL類型是什麼。也必須調整存儲過程調用來指示該過程返回一個值。
下面接著上面的例子。這次查詢Dylan Thomas逝世時的年齡。這次的存儲過程使用PostgreSQL的pl/pgsql:

createfunctionsnuffed_it_when(VARCHAR)returnsinteger'declare
poet_idNUMBER;
poet_ageNUMBER;
begin
--.
SELECTidINTOpoet_idFROMpoetsWHEREname=$1;
--getandreturntheage.
SELECTageINTOpoet_ageFROMdeathsWHEREmort_id=poet_id;
returnage;
end;'language'pl/pgsql';

另外,注意pl/pgsql參數名通過Unix和DOS腳本的$n語法引用。同時,也注意嵌入的注釋,這是和Java代碼相比的另一個優越性。在Java中寫這樣的注釋當然是可以的,但是看起來很凌亂,並且和SQL語句脫節,必須嵌入到Java String中。
下面是調用這個存儲過程的Java代碼:

connection.setAutoCommit(false);
CallableStatementproc=connection.prepareCall("{?=callsnuffed_it_when(?)}");
proc.registerOutParameter(1,Types.INTEGER);
proc.setString(2,poetName);
cs.execute();
intage=proc.getInt(2);

如果指定了錯誤的返回值類型會怎樣?那麼,當調用存儲過程時將拋出一個RuntimeException,正如你在ResultSet操作中使用了一個錯誤的類型所碰到的一樣。

復雜的返回值

如果這是存儲過程的全部功能,那麼存儲過程就不是其它遠程執行機制的替換方案了。存儲過程的功能比這強大得多。
當執行一個SQL查詢時,DBMS創建一個叫做cursor(游標)的資料庫對象,用於在返回結果中迭代每一行。ResultSet是當前時間點的游標的一個表示。這就是為什麼沒有緩存或者特定資料庫的支持,只能在ResultSet中向前移動。
某些DBMS允許從存儲過程中返回遊標的一個引用。JDBC並不支持這個功能,但是Oracle、PostgreSQL和DB2的JDBC驅動器都支持在ResultSet上打開到游標的指針(pointer)。
設想列出所有沒有活到退休年齡的詩人,下面是完成這個功能的存儲過程,返回一個打開的游標,同樣也使用PostgreSQL的pl/pgsql語言:

createprocerelist_early_deaths()returnrefcursoras'declare
toesuprefcursor;
begin
opentoesupforSELECTpoets.name,deaths.ageFROMpoets,deaths--allentriesindeathsareforpoets.--butthetablemightbecomegeneric.
WHEREpoets.id=deaths.mort_idANDdeaths.age<60;
returntoesup;
end;'language'plpgsql';

下面是調用該存儲過程的Java方法,將結果輸出到PrintWriter:
PrintWriter:

staticvoidsendEarlyDeaths(PrintWriterout){
Connectioncon=null;
CallableStatementtoesUp=null;
try{
con=ConnectionPool.getConnection();
//...con.
setAutoCommit(false);//Setupthecall.
CallableStatementtoesUp=connection.prepareCall("{?=calllist_early_deaths()}");
toesUp.registerOutParameter(1,Types.OTHER);
toesUp.execute();
ResultSetrs=(ResultSet)toesUp.getObject(1);
while(rs.next()){
Stringname=rs.getString(1);
intage=rs.getInt(2);
out.println(name+"was"+age+"yearsold.");
}
rs.close();
}
catch(SQLExceptione){//Weshouldprotectthesecalls.toesUp.close();con.close();
}
}

因為JDBC並不直接支持從存儲過程中返回遊標,使用Types.OTHER來指示存儲過程的返回類型,然後調用getObject()方法並對返回值進行強制類型轉換。
這個調用存儲過程的Java方法是mapping的一個好例子。Mapping是對一個集上的操作進行抽象的方法。不是在這個過程上返回一個集,可以把操作傳送進去執行。本例中,操作就是把ResultSet列印到一個輸出流。這是一個值得舉例的很常用的例子,下面是調用同一個存儲過程的另外一個方法實現:

publicclassProcessPoetDeaths{
publicabstractvoidsendDeath(Stringname,intage);
}
staticvoidmapEarlyDeaths(ProcessPoetDeathsmapper){
Connectioncon=null;
CallableStatementtoesUp=null;
try{
con=ConnectionPool.getConnection();
con.setAutoCommit(false);
CallableStatementtoesUp=connection.prepareCall("{?=calllist_early_deaths()}");
toesUp.registerOutParameter(1,Types.OTHER);
toesUp.execute();
ResultSetrs=(ResultSet)toesUp.getObject(1);
while(rs.next()){
Stringname=rs.getString(1);
intage=rs.getInt(2);
mapper.sendDeath(name,age);
}
rs.close();
}catch(SQLExceptione){//Weshouldprotectthesecalls.toesUp.close();
con.close();
}
}

這允許在ResultSet數據上執行任意的處理,而不需要改變或者復制獲取ResultSet的方法:

staticvoidsendEarlyDeaths(finalPrintWriterout){
ProcessPoetDeathsmyMapper=newProcessPoetDeaths(){
publicvoidsendDeath(Stringname,intage){
out.println(name+"was"+age+"yearsold.");
}
};
mapEarlyDeaths(myMapper);
}

這個方法使用ProcessPoetDeaths的一個匿名實例調用mapEarlyDeaths。該實例擁有sendDeath方法的一個實現,和我們上面的例子一樣的方式把結果寫入到輸出流。當然,這個技巧並不是存儲過程特有的,但是和存儲過程中返回的ResultSet結合使用,是一個非常強大的工具。

熱點內容
為什麼編譯一直出錯 發布:2024-11-24 19:30:24 瀏覽:234
如何查看qq仙境電腦配置 發布:2024-11-24 19:30:14 瀏覽:625
怎麼用蘋果玩安卓賬號 發布:2024-11-24 19:29:34 瀏覽:157
2022款雅閣哪個配置全景天窗 發布:2024-11-24 19:25:48 瀏覽:841
64解壓縮軟體官方下載 發布:2024-11-24 19:23:35 瀏覽:523
php圖形庫 發布:2024-11-24 19:21:02 瀏覽:496
c語言遞歸演算法n 發布:2024-11-24 19:18:46 瀏覽:32
在c語言中表示什麼 發布:2024-11-24 19:04:46 瀏覽:408
discuz友情鏈接緩存 發布:2024-11-24 19:00:11 瀏覽:693
資料庫時區 發布:2024-11-24 18:28:30 瀏覽:614