JDBC ResultSet 是应用程序级查询游标吗

Is the JDBC ResultSet an application-level query cursor

database cursor 定义与 JDBC ResultSet API.

惊人地相似

但尽管如此,MySQL doesn't support database cursors:

MySQL does not support SQL cursors, and the JDBC driver doesn't emulate them, so setCursorName() has no effect.

那么,JDBC 实现是否是一种模仿数据库游标实现的数据访问规范,即使数据库并不真正支持这样的功能?

你当然可以这么想。所有这些概念都是从 ODBC 继承而来的,所以您可以感谢(责备?)历史让事情变成这样。游标并没有得到大多数数据库的广泛支持,以至于 API 中提供的功能在 JDBC 中提供的全部范围内。具体来说,在 MySQL 中,从 MySQL 5.0 开始支持游标 "fetch",这意味着无论是否需要,都不会强制驱动程序读取整个结果。这意味着可以尽早放弃一个结果集而几乎没有成本。但是,需要额外的往返才能定期请求行块。 MySQL Connector/J 默认情况下不强制执行 FORWARD_ONLY 语义,并在允许 "scrollability" 的客户端中缓冲整个结果。但是,由于服务器中的实现,这不允许对其他事务中提交的更改敏感。功能通常 mimicked/emulated 在可能的情况下提供 API.

的便利

根据我对 JDBC ResultSet 的理解,我会说它不依赖于它连接的数据库,它的行为是相同的。

JDBC 将始终将默认行数(不是整个结果集)提取到您的本地内存中。一旦到达获取行的最后一行(比如通过执行 next() 并尝试访问下一行)并且如果结果中有更多行,那么将对数据库进行另一个往返调用以获取下一行一批行到本地内存。

即使您可以设置比平时要在本地内存中获取的行数,您也可以考虑使用 CachedRowSet。

当您在语句上设置 fetchSize() 时,您只是向 JDBC 驱动程序发出了您希望它应该获取多少的指令,但是 JDBC 驱动程序可以自由地忽略您的指示。我不知道 Oracle 驱动程序对 fetchSize() 做了什么。大多数时候,它观察到 MySQL JDBC 驱动程序将始终获取所有行,除非您将 fetchSize() 设置为 Integer.MIN_VALUE。

名字里有什么...

的确,ResultSet 和数据库游标在语义上是相似的。 The SQL:2011 standard 指定:

A cursor is a mechanism by which the rows of a table may be acted on (e.g., returned to a host programming language) one at a time.

这听起来很像 ResultSet。再往下,SQL:2011 标准继续并提到:

A cursor declaration descriptor and a result set descriptor have four properties: the sensitivity property (either SENSITIVE, INSENSITIVE, or ASENSITIVE), the scrollability property (either SCROLL or NO SCROLL), the holdability property (either WITH HOLD or WITHOUT HOLD), and the returnability property (either WITH RETURN or WITHOUT RETURN).

换句话说,none 这些功能是 "invented" 由 JDBC(或 ODBC)规范团队开发的。它们确实以这种形式存在于许多 SQL 数据库实现中,并且与任何规范一样,上述许多功能在 SQL 实现中也是可选的。

您已经在 之前获得了关于 MySQL 部分的权威回复。我想补充一点,JDBC,就像任何高层次的规范一样,有必需的部分和可选的部分。

查看JDBC Spec,我可以看到以下相关部分。

6.3 JDBC 4.2 API Compliance

A driver that is compliant with the JDBC specification must do the following:

[...]

It must implement the Statement interface with the exception of the following optional methods:

  • [...]
  • setCursorName
  • [...]

It must implement the ResultSet interface with the exception of the following optional methods:

  • [...]
  • getCursorName
  • [...]

ResultSet类型的实现也是如此。在规格的更下方,您会发现:

The method DatabaseMetaData.supportsResultSetType returns true if the specified type is supported by the driver and false otherwise.