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

时间:2022-03-15 22:53:34

The database cursor definition is strikingly resembling with the JDBC ResultSet API.

数据库游标定义与JDBC ResultSet API非常相似。

  • the database cursor can be forward-only just like ResultSet.TYPE_FORWARD_ONLY.

    数据库游标可以像ResultSet.TYPE_FORWARD_ONLY一样只向前转。

  • the database cursor can be scrollable and even have a sensitivity setting just like ResultSet.TYPE_SCROLL_SENSITIVE.

    数据库游标可以滚动,甚至可以像ResultSet.TYPE_SCROLL_SENSITIVE一样具有灵敏度设置。

  • there is also support for holdability like ResultSet.HOLD_CURSORS_OVER_COMMIT

    还有对ResultSet.HOLD_CURSORS_OVER_COMMIT等可保持性的支持

  • and even the support for positional update/delete is being replicated into JDBC ResultSet.CONCUR_UPDATABLE

    甚至对位置更新/删除的支持也被复制到JDBC ResultSet.CONCUR_UPDATABLE中

But in spite of all these resembling, MySQL doesn't support database cursors:

但是尽管有这些相似之处,MySQL并不支持数据库游标:

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

MySQL不支持SQL游标,并且JDBC驱动程序不会模拟它们,因此setCursorName()不起作用。

So, is the JDBC implementation a data access specification that mimics a database cursor implementation, even if the database doesn't really support such a feature?

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

3 个解决方案

#1


5  

You can certainly think of it that way. All of these concepts are inherited from ODBC so you can thank (blame?) history for things being this way. Cursors aren't widely supported by most dbs to the full extent that features are provided in APIs such as JDBC. In MySQL specifically, there is a cursor "fetch" supported as of MySQL 5.0 which means that the driver isn't forced to read the entire result, whether it's needed or not. This means that it is possible to abandon a result set early with little to no cost. However, an additional round-trip is required to request blocks of rows periodically. MySQL Connector/J doesn't enforce the FORWARD_ONLY semantics by default and buffers the entire result in the client allowing "scrollability". However, due to the implementation in the server, this does not allow for being sensitive to changes committed in other transactions. Features are typically mimicked/emulated where possible to provide the convenience of the API.

你当然可以这样想。所有这些概念都是从ODBC继承的,所以你可以感谢(责备?)历史记录。大多数dbs都没有广泛支持游标,因为在JDBC等API中提供了这些功能。特别是在MySQL中,从MySQL 5.0开始支持游标“fetch”,这意味着驱动程序不会被强制读取整个结果,无论是否需要。这意味着可以在很少或没有成本的情况下尽早放弃结果集。但是,需要额外的往返来定期请求行块。 MySQL Connector / J默认情况下不强制执行FORWARD_ONLY语义,并将整个结果缓存在客户端中,允许“可滚动性”。但是,由于服务器中的实现,这不允许对在其他事务中提交的更改敏感。通常可以模仿/模拟功能,以提供API的便利性。

#2


4  

What's in a name...

什么是名字......

Indeed, a ResultSet and a database cursor are semantically similar. The SQL:2011 standard specifies:

实际上,ResultSet和数据库游标在语义上是相似的。 SQL:2011标准指定:

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.

游标是一种机制,通过该机制,可以一次一个地对行的行进行操作(例如,返回到主编程语言)。

That does sound a lot like a ResultSet. Further down, the SQL:2011 standard goes on and mentions:

这听起来很像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).

游标声明描述符和结果集描述符有四个属性:sensitivity属性(SENSITIVE,INSENSITIVE或ASENSITIVE),可滚动性属性(SCROLL或NO SCROLL),可保持性属性(WITH HOLD或WITHOUT HOLD),以及返回属性(WITH RETURN或WITHOUT RETURN)。

In other words, none of these features were "invented" by the JDBC (or ODBC) spec teams. They do exist exactly in this form in many SQL database implementations, and as with any specs, many of the above features are optional in SQL implementations as well.

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

You've gotten an authoritative response on the MySQL part already by Jess. I'd like to add that JDBC, like any specification on a high level, has parts that are required and parts that are optional.

你已经在Jess已经对MySQL部分做出了权威的回应。我想补充说,JDBC与高级别的任何规范一样,具有所需的部分和可选的部分。

Looking at the JDBC Spec, I can see the following relevant parts.

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

6.3 JDBC 4.2 API Compliance

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

符合JDBC规范的驱动程序必须执行以下操作:

[...]

[...]

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

它必须实现Statement接口,但以下可选方法除外:

  • [...]
  • [...]
  • setCursorName
  • 调用setCursorName
  • [...]
  • [...]

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

它必须实现ResultSet接口,但以下可选方法除外:

  • [...]
  • [...]
  • getCursorName
  • 调用getCursorName
  • [...]
  • [...]

The same is true for the implementation of ResultSet types. Further down in the specs, you will find:

对于ResultSet类型的实现也是如此。在规格中,你会发现:

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

如果驱动程序支持指定的类型,则DatabaseMetaData.supportsResultSetType方法返回true,否则返回false。

#3


1  

Based on my understanding about JDBC ResultSet i will say it does not depends Database which it connects, its behaviour would be same.

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

JDBC will always fetches default number of rows (not the entire result set) to your local memory. Once you reach at the last line of the fetched rows (say by doing next() and try to access next row) and if there are more rows in the result, then another round-trip call will be made to the database to fetch next batch of rows to local memory.

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

Even you can set number of rows you want fetch in local memory than usual, you may consider CachedRowSet.

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

When you set the fetchSize() on the Statement, you are only giving a instruction to the JDBC driver how much you want it should fetch, but JDBC driver is free to ignore your instructions. I do not know what the Oracle driver does with the fetchSize(). Most of times its observed that MySQL JDBC driver will always fetch all rows unless you set the fetchSize() to Integer.MIN_VALUE.

在Statement上设置fetchSize()时,您只是向JDBC驱动程序发出了一个指令,指示它应该获取多少,但JDBC驱动程序可以忽略您的指令。我不知道Oracle驱动程序对fetchSize()的作用。大多数情况下,它观察到MySQL JDBC驱动程序将始终获取所有行,除非您将fetchSize()设置为Integer.MIN_VALUE。

#1


5  

You can certainly think of it that way. All of these concepts are inherited from ODBC so you can thank (blame?) history for things being this way. Cursors aren't widely supported by most dbs to the full extent that features are provided in APIs such as JDBC. In MySQL specifically, there is a cursor "fetch" supported as of MySQL 5.0 which means that the driver isn't forced to read the entire result, whether it's needed or not. This means that it is possible to abandon a result set early with little to no cost. However, an additional round-trip is required to request blocks of rows periodically. MySQL Connector/J doesn't enforce the FORWARD_ONLY semantics by default and buffers the entire result in the client allowing "scrollability". However, due to the implementation in the server, this does not allow for being sensitive to changes committed in other transactions. Features are typically mimicked/emulated where possible to provide the convenience of the API.

你当然可以这样想。所有这些概念都是从ODBC继承的,所以你可以感谢(责备?)历史记录。大多数dbs都没有广泛支持游标,因为在JDBC等API中提供了这些功能。特别是在MySQL中,从MySQL 5.0开始支持游标“fetch”,这意味着驱动程序不会被强制读取整个结果,无论是否需要。这意味着可以在很少或没有成本的情况下尽早放弃结果集。但是,需要额外的往返来定期请求行块。 MySQL Connector / J默认情况下不强制执行FORWARD_ONLY语义,并将整个结果缓存在客户端中,允许“可滚动性”。但是,由于服务器中的实现,这不允许对在其他事务中提交的更改敏感。通常可以模仿/模拟功能,以提供API的便利性。

#2


4  

What's in a name...

什么是名字......

Indeed, a ResultSet and a database cursor are semantically similar. The SQL:2011 standard specifies:

实际上,ResultSet和数据库游标在语义上是相似的。 SQL:2011标准指定:

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.

游标是一种机制,通过该机制,可以一次一个地对行的行进行操作(例如,返回到主编程语言)。

That does sound a lot like a ResultSet. Further down, the SQL:2011 standard goes on and mentions:

这听起来很像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).

游标声明描述符和结果集描述符有四个属性:sensitivity属性(SENSITIVE,INSENSITIVE或ASENSITIVE),可滚动性属性(SCROLL或NO SCROLL),可保持性属性(WITH HOLD或WITHOUT HOLD),以及返回属性(WITH RETURN或WITHOUT RETURN)。

In other words, none of these features were "invented" by the JDBC (or ODBC) spec teams. They do exist exactly in this form in many SQL database implementations, and as with any specs, many of the above features are optional in SQL implementations as well.

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

You've gotten an authoritative response on the MySQL part already by Jess. I'd like to add that JDBC, like any specification on a high level, has parts that are required and parts that are optional.

你已经在Jess已经对MySQL部分做出了权威的回应。我想补充说,JDBC与高级别的任何规范一样,具有所需的部分和可选的部分。

Looking at the JDBC Spec, I can see the following relevant parts.

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

6.3 JDBC 4.2 API Compliance

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

符合JDBC规范的驱动程序必须执行以下操作:

[...]

[...]

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

它必须实现Statement接口,但以下可选方法除外:

  • [...]
  • [...]
  • setCursorName
  • 调用setCursorName
  • [...]
  • [...]

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

它必须实现ResultSet接口,但以下可选方法除外:

  • [...]
  • [...]
  • getCursorName
  • 调用getCursorName
  • [...]
  • [...]

The same is true for the implementation of ResultSet types. Further down in the specs, you will find:

对于ResultSet类型的实现也是如此。在规格中,你会发现:

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

如果驱动程序支持指定的类型,则DatabaseMetaData.supportsResultSetType方法返回true,否则返回false。

#3


1  

Based on my understanding about JDBC ResultSet i will say it does not depends Database which it connects, its behaviour would be same.

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

JDBC will always fetches default number of rows (not the entire result set) to your local memory. Once you reach at the last line of the fetched rows (say by doing next() and try to access next row) and if there are more rows in the result, then another round-trip call will be made to the database to fetch next batch of rows to local memory.

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

Even you can set number of rows you want fetch in local memory than usual, you may consider CachedRowSet.

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

When you set the fetchSize() on the Statement, you are only giving a instruction to the JDBC driver how much you want it should fetch, but JDBC driver is free to ignore your instructions. I do not know what the Oracle driver does with the fetchSize(). Most of times its observed that MySQL JDBC driver will always fetch all rows unless you set the fetchSize() to Integer.MIN_VALUE.

在Statement上设置fetchSize()时,您只是向JDBC驱动程序发出了一个指令,指示它应该获取多少,但JDBC驱动程序可以忽略您的指令。我不知道Oracle驱动程序对fetchSize()的作用。大多数情况下,它观察到MySQL JDBC驱动程序将始终获取所有行,除非您将fetchSize()设置为Integer.MIN_VALUE。