Jaybird(Firebird JDBC)ResultSet FetchSize - 分页持久查询

时间:2016-02-19 17:11:32

标签: java jdbc pagination firebird jaybird

我正试图找到一种方法如何强制jaybird在ResultSet中进行“分页”。假设我们有一些持久的sql查询(它在15秒内返回例如5000行)。但是,获取前50个(随机)行只需要几分之一秒。只要我们不向查询添加order by子句,服务器就会快速返回第一行,这些行可以立即显示在客户端应用程序中。这是火焰客户端的默认行为。

我尝试通过设置Statement参数来模拟此行为,如下面的代码所示,但没有成功。有没有办法强制jaybird不要将所有行加载到ResultSet?我想方法stmt.setFetchSize(50)有这个目的,但它可能是错误的。使用的Jaybird版本是2.2.7,使用的Firebird版本是2.5.4。谢谢你的建议。

String user = "user";
String pass = "pass";
Connection conn = DriverManager.getConnection(s, user, pass);
conn.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);
conn.setAutoCommit(false);
Statement stmt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
stmt.setFetchSize(50);
stmt.setFetchDirection(ResultSet.FETCH_FORWARD);
ResultSet rs = null;
String sql = "select * from TABLE"; //long lasting select 
boolean ok = stmt.execute(sql);
if (ok) {
    rs = stmt.getResultSet();
    while (rs.next()) {
         //do something
    }
}
if (rs != null) {
    rs.close();
}

if (stmt != null) {
    stmt.close();
}

我尝试实现与flamerobin客户端一样的想法 - 将数据快速加载到表中(仅当我们需要它们时 - 向下滚动到表中)。我们开发了应用程序,它是两层ERP系统(DB服务器firebird,netbeans平台上的客户端)的客户端。我们编写了一些数据库组件,它们使用与“interbase Delphi组件”相同的原理填充JXTable数据。上面的代码是简化的,在组件代码中我们将前100行加载到JTable表模型,当用户向下滚动时我们加载另外100行等。但是我注意到前100行的加载时间与以下相同我们将所有行加载到数据集。那是代码

boolean ok = stmt.execute(sql);
if (ok) {
    rs = stmt.getResultSet();
    int rows = 0;
    while (rs.next() rows < 100) {
         //do something
         rows++;
    }
}

实际上与第一块源代码相同。似乎stmt.execute(sql)命令等待,直到从服务器返回所有选择行。但是我设置我想获得50行块,所以我认为while循环将在从DB服务器获取前50行后立即启动。所以我想在获取前50行之后启动while循环(就好像我设置了stmt.setMaxRows(50)),但我希望机会让结果集打开并按需获取另一行。

1 个答案:

答案 0 :(得分:0)

使用defaultHoldable通常会完全符合您的预期:它将以指定大小的批量获取行(Firebird 3可以决定在批量过大时返回较少)。

但是,由于您在连接字符串中指定了HOLD_CURSORS_OVER_COMMIT,因此结果集为CLOSE_CURSORS_AT_COMMIT,并且可保留的结果集在返回之前完全缓存在客户端。

您需要为此特定语句将可保持性设置为defaultHoldable,或者 - 如果对所有语句执行此操作 - 只需从连接字符串中删除CODE: int min=1; int max=10; int y=0; Random rand = new Random(); for(int count=0;count<1;count++){ int randomNum = rand.nextInt((max - min) + 1) + min; arr[count] = randomNum; } System.out.println(arr[0]);//for checking System.out.println(randomNum);//for checking