ResultSet.TYPE_SCROLL_SENSITIVE 的行为
我对 TYPE_SCROLL_SENSITIVE
类型的 ResultSet
的行为感到困惑。
我对此的理解是:
- 我执行一个选择查询,该查询返回一个结果集。我打印出第一行中特定列的值。
- 然后,我执行 Thread.sleep(10000),这会使程序暂停 10 秒。
- 当程序处于睡眠状态时,我手动对数据库中的同一列进行更新(通过 SQL 提示符)。
- 10 秒后,我再次打印结果集第一行中同一列的值。
在步骤 4 中,我希望打印的列值与步骤 1 中打印的值不同。但我总是得到相同的值(即使我的 ResultSet
类型为 SCROLL_TYPE_SENSITIVE
)。
我在这里误解了什么吗?
下面是我使用的代码。
private void doStuff() throws Exception
{
final String query = "select * from suppliers where sup_id=420";
Statement stmt = this.con.createStatement(
ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
ResultSet rs = stmt.executeQuery(query);
rs.next();
System.out.println("City : " + rs.getString("city"));
Thread.sleep(10000); // While this executes, I do a manual update !
System.out.println("City : " + rs.getString("city"));
}
I am confused about the behaviour of a ResultSet
that is of type TYPE_SCROLL_SENSITIVE
.
My understanding of this is:
- I execute a select query that returns me a result set. I print out the value of a particular column in the first row.
- I then execute
Thread.sleep(10000)
, which halts the program for 10 seconds. - While the program is sleeping, I manually do an update to the same column in the DB (through the SQL prompt).
- After 10 seconds, I again print the value of the same column in the first row of the result set.
In step 4, I expect the printed column value to be different from the value printed in step 1. But I always get the same value (even if my ResultSet
is of type SCROLL_TYPE_SENSITIVE
).
Am I misunderstanding something here ?
Below is the code I use.
private void doStuff() throws Exception
{
final String query = "select * from suppliers where sup_id=420";
Statement stmt = this.con.createStatement(
ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
ResultSet rs = stmt.executeQuery(query);
rs.next();
System.out.println("City : " + rs.getString("city"));
Thread.sleep(10000); // While this executes, I do a manual update !
System.out.println("City : " + rs.getString("city"));
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
是的。您必须再次获取表的最新状态,方法是自行启动
SELECT
或调用ResultSet.refreshRow()
。此外,请阅读ResultSet.refreshRow()
之前使用它,否则你可能会得到意想不到的结果。该文档声明有关 TYPE_SCROLL_SENSITIVE,
这仅仅意味着它会对同一 ResultSet 对象中其他人所做的更改敏感。要理解这个概念,我建议查看官方 JDBC 教程:更新表。
好的,编辑我的帖子以包含原始教程中的特定行,
Yes. You must fetch again to get the latest state of the table, either by firing up a
SELECT
yourself, or callingResultSet.refreshRow()
. Moreover, read the docs ofResultSet.refreshRow()
before using it, otherwise you might get unexpected results.The doc states regarding TYPE_SCROLL_SENSITIVE,
Which merely means that it would be sensitive to the changes made by others in the same ResultSet object. To understand the concept, I would advise to look at this official JDBC Tutorial: Updating Tables.
Okay, editing my post to include the specific line from the original tutorial,
我认为您正在使用 mysql 作为数据库,这是一个已知的错误。
让我详细说明一下 -
根据 java 站点上的 Oracle 文档,TYPE_SCROLL_SENSITIVE 用于 2 个目的 -
1.Mysql 驱动程序现在可以来回移动 jdbc 结果集的指针
(否则只是向前移动),所以基本上滚动已启用
{所以现在你可以执行 resultset.previous() 并且指针将返回}
2.显示对数据库所做的更新值(内部更改)。
你被困在第二点......
看到你的程序不工作,因为你从未使用过 fetchSize() 的概念;
每当使用 jdbc 时,驱动程序都会将默认行数提取到显示的缓存中(例如:oracle 默认加载 10 行),
因此 TYPE_SCROLL_SENSITIVE 将仅显示下一次缓存重新加载的更新值。
就像数据库中有 100 行,您更新了所有行,但直到那时只提取了 10 行,因此您将随后打印更新的其他 90 行,因为驱动程序将在 9 轮缓存管理中加载这些表。
为了显式定义要获取的行数(例如将 oracle 的行数从 10 更改为 1),您可以在创建语句时显式定义 fetchSize()。(但无效地使用缓存,最终会降低速度)
因此,在初始化语句时,
添加一行 as:
create resultSet as:
验证数据:从 resultSet 打印 setFetchSize,如果它从语句传递到 resultSet,而 Sysout 则获取配置已被保存,如:
如果 sysout 给出 ' 1' 作为获取大小,您将看到程序的动态更新,
但如果它给出“0”,则意味着您的数据库不支持 fetchSize() 的动态初始化;
这里是mysql的问题,mysql默认会获取所有的行数到ResultSet中,因此动态内部更新时,不会获取动态值。
(内部更新是由同一程序的其他线程完成的更新)。
以下是支持我关于 sql bug 观点的 bug:
sql bugs fetchSize Bug
orcale 文档 TYPE_SCROLL_SENSITIVE 示例 ResultSet5.java
I Think you are using mysql as your db,and this is a known bug.
Let me elaborate fully-
As per Oracle documentation on the java site TYPE_SCROLL_SENSITIVE is used for 2 purposes-
1.Mysql driver can now move the jdbc result set's pointer to and fro
(which otherwise just goes in the forward direction),so basically scrolling is enabled
{so now you can do resultset.previous() and the pointer will go back}
2.To show updated values(the internal changes),made to the database.
You are stuck at the 2nd point...
See your program is not working,because you never used the concept of fetchSize();
whenever using jdbc,the driver fetches a default number of rows into the cache that is displayed(for ex:oracle loads 10 rows by default)
so TYPE_SCROLL_SENSITIVE will display the updated value of the next cache reload only.
it is like you have 100 rows in the DB,you updated all,but till then only 10 rows were fetched,so you will get the other 90 rows updated printed subsequently ,as the driver will load these tables in 9 rounds of cache management.
for explicitly defining the number of rows to be fetched(for example changing the no. of rows from 10 to 1 for oracle) you can explicitly define the fetchSize() while creating statement.(but using cache ineffectively,at the end slows the speed )
so while initializing statement as:
add a line as:
create resultSet as:
to verify the data: print setFetchSize from resultSet,if it passes from statement to resultSet while Sysout than the fetching configuration has been saved,as:
if the sysout gives '1' as fetch size,you will see your dynamic updates from the program as it is,
but if it gives '0' that means your DB doesnot support dynamic initialization of fetchSize();
Here is the problem with mysql,mysql by default fetches all the number of rows into the ResultSet,and thus the dynamic internal update,does not fetch the dynamic values.
(internal update is the update done by some other thread of the same program).
Here is the bug supporting my point on sql bugs:
sql bugs fetchSize Bug
orcale docs TYPE_SCROLL_SENSITIVE example ResultSet5.java