0

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

我尝试通过设置以下代码中的 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();
}

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

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 循环将在从数据库服务器获得前 50 行后立即开始。所以我想在获取前 50 行后开始 while 循环(就像我设置了 stmt.setMaxRows(50)),但我希望有机会让结果集打开并按需获取另一行。

4

1 回答 1

0

使用setFetchSize通常完全符合您的期望:它将以指定大小的批次获取行(当 Firebird 3 认为批次太大时,它可以决定返回更少)。

但是,正如您defaultHoldable在连接字符串中指定的那样,结果集是HOLD_CURSORS_OVER_COMMIT,并且可保存的结果集在返回之前被完全缓存在客户端。

您需要CLOSE_CURSORS_AT_COMMIT为此特定语句设置可保留性,或者 - 如果您为所有语句执行此操作 - 只需defaultHoldable从连接字符串中删除 。

于 2016-02-20T08:36:12.857 回答