此 Microsoft SQL Server JDBC 驱动程序示例应用程序说明了如何从数据库中检索大量数据,然后使用 SQLServerResultSet 对象的 setFetchSize 方法控制在客户端中缓存的数据行数。
要对客户端中缓存的行数进行限制,首先必须在创建 Statement 对象时使用服务器端游标,并且在创建 Statement 对象时专门声明要使用的游标类型。例如,JDBC 驱动程序提供了 TYPE_SS_SERVER_CURSOR_FORWARD_ONLY 游标类型,该类型是用于 SQL Server 数据库的快速只进、只读的服务器端游标。
运行完 Statement 对象中包含的查询且数据已经以结果集的形式返回到客户端后,可以调用 setFetchSize 方法来控制一次可从数据库中检索的数据量。例如,某表格包含 100 行数据,提取大小设置为 10,则无论何时,客户端中都仅缓存 10 行数据。尽管这样会降低数据处理速度,但其优势是所占用的客户端内存较少,这在需要处理大量数据时尤为有用。
此示例的代码文件名为 cacheRS.java,该文件可在以下位置找到:
<安装目录>\sqljdbc_<版本>\<语言>\help\samples\resultsets
要求
若要运行此示例应用程序,必须将 classpath 设置为包含 sqljdbc.jar 文件或 sqljdbc4.jar 文件。如果 classpath 缺少 sqljdbc.jar 项或 sqljdbc4.jar 项,示例应用程序将引发“找不到类”的常见异常。还需要访问 SQL Server 2005 AdventureWorks 示例数据库。有关如何设置 classpath 的详细信息,请参阅使用 JDBC 驱动程序。
示例
在下面的示例中,示例代码将建立与 AdventureWorks 示例数据库的连接。接下来,它会使用带有 SQLServerStatement 对象的 SQL 语句,指定服务器端游标类型,然后运行 SQL 语句并将所返回的数据放入 SQLServerResultSet 对象。
随后,示例代码调用自定义的 timerTest 方法,需要传递的参数为要使用的提取大小和结果集。timerTest 方法接下来将使用 setFetchSize 方法设置结果集的提取大小,设置测试的起始时间,然后使用 While
循环遍历结果集。 While
循环退出后,该代码立即设置测试的停止时间,然后显示测试结果,其中包括提取大小、已处理的行数以及执行该测试所用的时间。
import java.sql.*; import com.microsoft.sqlserver.jdbc.SQLServerResultSet; public class cacheRS { public static void main(String[] args) { // Create a variable for the connection string. String connectionUrl = "jdbc:sqlserver://localhost:1433;" + "databaseName=AdventureWorks;integratedSecurity=true;"; // Declare the JDBC objects. Connection con = null; Statement stmt = null; ResultSet rs = null; try { // Establish the connection. Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); con = DriverManager.getConnection(connectionUrl); // Create and execute an SQL statement that returns a large // set of data and then display it. String SQL = "SELECT * FROM Sales.SalesOrderDetail;"; stmt = con.createStatement(SQLServerResultSet.TYPE_SS_SERVER_CURSOR_FORWARD_ONLY, + SQLServerResultSet.CONCUR_READ_ONLY); // Perform a fetch for every row in the result set. rs = stmt.executeQuery(SQL); timerTest(1, rs); rs.close(); // Perform a fetch for every tenth row in the result set. rs = stmt.executeQuery(SQL); timerTest(10, rs); rs.close(); // Perform a fetch for every 100th row in the result set. rs = stmt.executeQuery(SQL); timerTest(100, rs); rs.close(); // Perform a fetch for every 1000th row in the result set. rs = stmt.executeQuery(SQL); timerTest(1000, rs); rs.close(); // Perform a fetch for every 128th row (the default) in the result set. rs = stmt.executeQuery(SQL); timerTest(0, rs); rs.close(); } // Handle any errors that may have occurred. catch (Exception e) { e.printStackTrace(); } finally { if (rs != null) try { rs.close(); } catch(Exception e) {} if (stmt != null) try { stmt.close(); } catch(Exception e) {} if (con != null) try { con.close(); } catch(Exception e) {} } } private static void timerTest(int fetchSize, ResultSet rs) { try { // Declare the variables for tracking the row count and elapsed time. int rowCount = 0; long startTime = 0; long stopTime = 0; long runTime = 0; // Set the fetch size then iterate through the result set to // cache the data locally. rs.setFetchSize(fetchSize); startTime = System.currentTimeMillis(); while (rs.next()) { rowCount++; } stopTime = System.currentTimeMillis(); runTime = stopTime - startTime; // Display the results of the timer test. System.out.println("FETCH SIZE: " + rs.getFetchSize()); System.out.println("ROWS PROCESSED: " + rowCount); System.out.println("TIME TO EXECUTE: " + runTime); System.out.println(); } catch (Exception e) { e.printStackTrace(); } } }