【问题标题】:Jaybird (Firebird JDBC) ResultSet FetchSize -- Pagination long lasting queriesJaybird (Firebird JDBC) ResultSet FetchSize -- 分页持久查询
【发布时间】:2016-02-19 17:11:31
【问题描述】:

我正在尝试找到一种方法来强制 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)),但我希望有机会让结果集打开并按需获取另一行。

【问题讨论】:

  • 设置获取大小将指示 jaybird 以 50 为一组获取行(尽管某些 Firebird 版本可能会选择返回较小的数字)。但是,它不会限制返回的行数。您的代码仍在获取所有行,只是每批 50 行。您要达到什么目的?如果您最初只想返回 50 次,则不应调用 next() 超过 50 次,或使用setMaxRows
  • 问题被附加(完成)作为对 Mark Rotteveel 评论的回应。
  • 您是否在连接字符串中使用defaultResultSetHoldable=true
  • 我的连接地址是 jdbc:firebirdsql:server:/path/db.fdb?encoding=UTF8&dialect=3&defaultHoldable
  • 如果您使用defaultResultSetHoldable,则会立即检索整个结果集。

标签: java jdbc pagination firebird jaybird


【解决方案1】:

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

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

您需要将此特定语句的可保留性设置为 CLOSE_CURSORS_AT_COMMIT,或者 - 如果您对所有语句都这样做 - 只需从连接字符串中删除 defaultHoldable

【讨论】:

    猜你喜欢
    • 2021-01-06
    • 2018-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-19
    • 2016-12-16
    • 1970-01-01
    • 2015-12-15
    相关资源
    最近更新 更多