IBM DB2 Driver for JDBC and SQLJ 提供了一個名為 useRowsetCursor 的數據源屬性,其預設值為 true。這意味著在伺服器支援的情況下,驅動程式會嘗試對可捲動游標使用多行獲取(MRF)。該屬性允許應用程式在必要時關閉 MRF。目前尚無針對前向游標的 MRF 支援,且 T2zos (DB2 V9 for z/OS) 早期版本不支援 MRF。
目前 MRF 支援有三個公共介面:
public void setUseRowsetCursor(boolean useRowsetCursor);
public boolean getUseRowsetCursor();
public boolean getUseRowsetCursor(java.util.Properties properties);
然而,這無法作為 T2zos 的通用解決方案,因為 T2zos 需要行集支援來獲得預設的 false 或 unset。這導致需要新的屬性來覆蓋現有的 useRowsetCursor 屬性(詳見下文「新連接屬性」一節)。此外,對於 T2zos,新屬性可同時用於前向游標和可捲動游標。在 IBM DB2 Driver for JDBC and SQLJ 版本 3.7.xx、3.51.xx、4.1.xx 及更新版本中,已啟用 MRF for T2zos (DB2 V9 for z/OS) 的額外支援。
多行獲取允許您從結果表中一次獲取 0 行或多行。與單行獲取不同,您可以獲取一組行(稱為行集)。
如圖 1 所示,透過一次獲取多行,應用程式減少了 SQL 呼叫,並可使用一條 FETCH 語句獲取行集。這不僅減少了 SQL Application Programming Interface (API) 的交互次數,還降低了應用程式的 CPU 使用率。
與 MRF 相關的新連接屬性是 enableRowsetSupport,其可用值包括:
NOT_SET(預設值)YESNO當 enableRowsetSupport 設為 YES 或 NO 時,它會覆蓋 useRowsetCursor 的當前設定。
NOT_SET,表示無 MRF 支援。NOT_SET 會使用 useRowsetCursor 的當前值(預設為 true),即僅在伺服器支援時對可捲動游標使用 MRF。用戶可將 useRowsetCursor 設為 false 或 enableRowsetSupport 設為 NO 來關閉該行為。若要啟用 MRF,將 enableRowsetSupport 設為 YES。若伺服器支援,T2zos 將對可捲動游標和前向游標均使用 MRF。未來 T4 和 T2u 可能選擇僅對前向游標使用 MRF。若要禁用 MRF,將 enableRowsetSupport 設為 NO,這將對所有類型的用戶(T2zos、T4、T2u)禁用 MRF。
public void setEnableRowsetSupport(int enableRowsetSupport);
public int getEnableRowsetSupport();
public int getEnableRowsetSupport(java.util.Properties properties);
清單 1 示範如何使用新的 enableRowsetSupport 連接屬性覆蓋 useRowsetCursor。程式將 enableRowsetSupport 設為 YES 以啟用 MRF。
import java.sql.*;
public class connectionInfo_MRF {
public static void main(String[] args) throws Exception {
System.out.println("\nTest case begins !!!\n ");
javax.sql.DataSource ds = new com.ibm.db2.jcc.DB2SimpleDataSource();
((com.ibm.db2.jcc.DB2BaseDataSource) ds).setServerName("ServerName");
((com.ibm.db2.jcc.DB2BaseDataSource) ds).setPortNumber(portNumber);
((com.ibm.db2.jcc.DB2BaseDataSource) ds).setDatabaseName("databaseName");
((com.ibm.db2.jcc.DB2BaseDataSource) ds).setDriverType(2);
// Enable MRF support. To disable MRF, set setEnableRowsetSupport to com.ibm.db2.jcc.DB2BaseDataSource.NO
int setValue = com.ibm.db2.jcc.DB2BaseDataSource.YES;
((com.ibm.db2.jcc.DB2BaseDataSource)ds).setEnableRowsetSupport(setValue);
((com.ibm.db2.jcc.DB2BaseDataSource) ds).setTraceFile("jccTrace.txt");
System.out.println(((com.ibm.db2.jcc.DB2BaseDataSource) ds).getJccVersion());
java.sql.Connection con = ds.getConnection("userName", "passWord");
// Get Rowset support value. When MRF is enabled this should return value 1.
int RowSet = ((com.ibm.db2.jcc.DB2BaseDataSource)ds).getEnableRowsetSupport();
System.out.println("\nRow Set Support value :" + RowSet);
System.out.println("\n");
// Set the cursor type to scrollable.
// Modify the below statement if you want the cursor type to be TYPE_FORWARD_ONLY
java.sql.Statement s = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
ResultSet.CONCUR_READ_ONLY);
// Create table
s.executeUpdate("create table TestQBatch (col1 int)");
// Populate tables with data.
for (int i = 1; i < 1000; i++) {
s.executeUpdate("insert into TestQBatch values (" + i + ")");
}
java.sql.ResultSet rs = s.executeQuery("Select * from TestQBatch");
while (rs.next()) {
System.out.print(rs.getInt(1) + " ");
}
// When MRF is enabled, ResultSet.getFetchSize() should always return value > 1.
int ActualResult = rs.getFetchSize();
System.out.print("\n\nFetch Size :" + ActualResult);
// Drop the table created.
s.executeUpdate("DROP TABLE TestQBatch");
System.out.println("\n\nTest case Ends !!! ");
con.commit();
}
}
在包含 IBM DB2 Driver for JDBC and SQLJ 版本 3.7.xx、3.51.xx、4.1.xx 或更新版本的 T2zos (DB2 V9 for z/OS) 機器上運行清單 1 中的範例程式。找到名為 jccTrace.txt 的 JCC 追蹤檔案。如前所述,在支援 MRF 的 T2zos 伺服器上,若 enableRowsetSupport 設為 YES,T2zos 會為游標準備 WITH ROWSET POSITIONING。
jccTrace.txt 包含字串 WITH ROWSET POSITIONING,表示已啟用 MRF。您也可透過呼叫 ResultSet.getFetchSize() 確定特定 ResultSet 的 MRF 是否活躍。若 fetchSize 回傳值大於 1,則表示使用了 MRF。注意,這是在 ResultSet 而非 PreparedStatement 上呼叫。
enableRowsetSupport=YES 且伺服器支援 MRF,T2zos 會為游標準備 WITH ROWSET POSITIONING。但若游標中出現大型物件 (LOB) 或 XML,且漸進式流使用預設值或設為 on,則會對 FETCH 語句關閉 MRF(OFF),並重新準備不含行集定位的 FETCH 語句。T2zosCursor.getMoreData_) 呼叫期間,可能拋出 -225 sqlcode。使用多行獲取 (MRF),您可以獲得比使用 FETCH 語句每次獲取一行更佳的性能。本文幫助您理解 MRF 及其使用方式,並透過範例 Java 程式示範如何在程式中設定 MRF,同時解釋如何確定是否使用了 MRF。
IBM Data Server Driver for JDBC and SQLJ 支援執行遵循 JDBC 1 標準的定位 UPDATE 或 DELETE 操作。對於行集游標,JDBC 1 定位更新語法必須知道行集的存在,格式如下:
update table set.... where current of cursor for row N of rowset
若應用程式想使用 JDBC 1 定位 UPDATE,必須構建正確的定位 UPDATE/DELETE 語句。但目前的 t2zos 應用程式仍使用舊格式:
update table set....where current of cursor
因此,行集支援導致不同行為:UPDATE 會影響整個行集而非單行。故 t2zos 行集支援預設為 false(見「新連接屬性」一節)。
該技術涉及使用 ResultSet.getCursorName 取得游標名稱,並按以下格式定義定位 UPDATE 或 DELETE:
UPDATE table SET col1=value1…coln=valueN WHERE CURRENT OF cursorname
DELETE FROM table WHERE CURRENT OF cursorname
若在支援多行獲取的資料源上使用 JDBC 1 技術執行 UPDATE 或 DELETE,定位語句可能更新或刪除多行,即使您僅想操作單行。
為避免非預期操作,可採取以下措施:
FOR ROW n OF ROWSET 子句,以識別需修改或刪除的特定行。