H2数据库支持滚动吗

does H2 database support scrolling

我正在尝试使用滚动来遍历 table 的所有记录。 代码和查询真的很简单。

// a really really simple query
String hql = "from " + MyTable.class.getSimpleName();

Query query = session.createQuery(hql);
query.setReadOnly(true);
query.setFetchSize(Integer.MIN_VALUE);

// An exception is caused here
ScrollableResults results = query.scroll(ScrollMode.FORWARD_ONLY);

// My code would have continued by iterating the results
while (results.next()) { ... }

但这会导致 GenericJDBCException"could not execute query using scroll"

org.hibernate.exception.GenericJDBCException: could not execute query using scroll
  at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:54)
  at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:125)
  at org.hibernate.loader.Loader.scroll(Loader.java:2632)
  at org.hibernate.loader.hql.QueryLoader.scroll(QueryLoader.java:557)
  at org.hibernate.hql.internal.ast.QueryTranslatorImpl.scroll(QueryTranslatorImpl.java:408)
  at org.hibernate.engine.query.spi.HQLQueryPlan.performScroll(HQLQueryPlan.java:268)
  at org.hibernate.internal.SessionImpl.scroll(SessionImpl.java:1346)
  at org.hibernate.internal.QueryImpl.scroll(QueryImpl.java:89)
  ...
Caused by: org.h2.jdbc.JdbcSQLException: Invalid value "-2147483648" for parameter "rows" [90008-172]
  at org.h2.message.DbException.getJdbcSQLException(DbException.java:329)
  at org.h2.message.DbException.get(DbException.java:169)
  at org.h2.message.DbException.getInvalidValueException(DbException.java:215)
  at org.h2.jdbc.JdbcStatement.setFetchSize(JdbcStatement.java:399)
  at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.setFetchSize(NewProxyPreparedStatement.java:1722)
  at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1886)
  at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1836)
  at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1816)
  at org.hibernate.loader.Loader.scroll(Loader.java:2595)
  ... 15 more

可能是 H2 数据库不支持滚动,还是我做错了什么?

下面一行是错误的:

query.setFetchSize(Integer.MIN_VALUE);

Integer.MIN_VALUE 是告诉 JDBC 使用流式传输的技巧。但是这个技巧(仅)被 MySQL 支持,而不是 H2。

来自the MySQL documentation

The combination of a forward-only, read-only result set, with a fetch size of Integer.MIN_VALUE serves as a signal to the driver to stream result sets row-by-row. After this, any result sets created with the statement will be retrieved row-by-row.

堆栈跟踪显示异常 "an invalid value -2147483648 for parameter rows." 此值正好是 -2^31 (= Integer.MIN_VALUE)。 H2 不知道如何处理负的获取大小并抛出异常。

结论:滚动适用于 H2 数据库。