JDBC类型滚动不敏感和敏感



在浏览Java JDBC ResultSet Types时,有两种滚动类型type_scroll_SENSITIVE和type_SCRollL_INSENSITIVE,我已经理解了。但当我去实际执行时,我没有看到效果。以下是代码:

package com.jdbc.resultsettypeandconcurrency;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class TypeInSensitiveConcurUpdate {
public static void main(String[] args) {
Connection con = null;
Statement stmt = null;
try {
System.out.println("loading the driver.....");
Class.forName("oracle.jdbc.driver.OracleDriver");
System.out.println("Driver loaded");
con = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl", "user", "pass");
if(con!=null) {
System.out.println("Connected to database");
} else {
System.out.println("Could not Get Connection");
}
stmt = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
String query = "select COF_NAME, SUP_ID, PRICE, SALES, TOTAL from COFFEES";
ResultSet rs = stmt.executeQuery(query);
System.out.println();
int cnt = 1;
while(rs.next()) {
System.out.print(rs.getString("COF_NAME")+", ");
System.out.print(rs.getInt("SUP_ID")+", ");
System.out.print(rs.getFloat("PRICE")+", ");
System.out.print(rs.getInt("SALES")+", ");
System.out.print(rs.getInt("TOTAL")+"n");
if(cnt == 2){
try {
Thread.sleep(20 * 1000);/**LINE:39*/
} catch (InterruptedException e) {
e.printStackTrace();
}
}
cnt++;
}
System.out.println();
} catch(ClassNotFoundException e) {
System.out.println("ClassNotFoundException : Driver Class not found");
System.out.println(e.getMessage());
} catch(SQLException e) {
System.out.println("SQL Error "+e.getMessage());
System.out.println(e.getErrorCode());
} finally {
if(stmt!=null) {
stmt.close();
}
if(con!=null) {
con.close();
}
System.out.println("All Connection closed");
}
}
}

当程序到达第39行时,我从后台更新数据库以获取记录。对于TYPE_SCROLL_INSENSITIVE,它不显示应该执行的更新记录,但对于TYPE_SCROLL_SENSITIVE,它不执行所需的行为。它必须显示更新的记录,但不显示。有人能说出为什么会这样吗?

当我在谷歌上搜索(不是Javadoc或JLS)时,我在某个地方读到ODBC瘦驱动程序、OCI驱动程序支持INSENSITIVE ResultSet对象并且不敏感。是这样吗?如果是,为什么以及哪个驱动程序支持两者?如果没有,那么我哪里错了。

我浏览了链接,但没有指出我的问题。如有任何建议,我们将不胜感激。

编辑:添加这些行以检查支持

DatabaseMetaData meta = con.getMetaData();
System.out.println("{TYPE_SCROLL_INSENSITIVE, CONCUR_UPDATABLE} -> "+
meta.supportsResultSetConcurrency(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE));
System.out.println("{TYPE_SCROLL_SENSITIVE, CONCUR_UPDATABLE} -> "+
meta.supportsResultSetConcurrency(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE));
System.out.println("{TYPE_SCROLL_SENSITIVE, CONCUR_READ_ONLY} -> "+
meta.supportsResultSetConcurrency(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY));

以下是我得到的结果:

{TYPE_SCROLL_INSENSITIVE,CONCUR_UPDATABLE}->真

{TYPE_SCROLL_SENSITIVE,CONCUR_UPDABLE}->真实

{TYPE_SCROLL_SENSITIVE,CONCUR_READ_ONLY}->真

不起作用的其他功能一样,在使用它们之前必须阅读文档。

重要的是窗口的概念

Oracle实现的滚动敏感结果集涉及窗口的概念,窗口大小基于获取大小。窗口大小会影响结果集中行的更新频率。

因此,要观察每一行的变化,必须将获取大小设置为1。

请注意,无法设置resultSet的提取大小,因为默认的提取大小为10,并且此更改仅对第11行及后续行有效。

因此,必须在prepareStatement:上设置提取大小

def stmt = con.prepareStatement("""select id, val from test
where  id between ? and ?  order by id""", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE)
stmt.setFetchSize(1)
// set bind variables and execute statement

现在,每次调用rs.next()时,都会打开一个新窗口,从而导致refreshRow的内部调用

其从数据库中获取当前值。

请注意,这个bahaviour只对TYPE_SCROLL_SENSITIVE执行,对TYPE_SCROLL_INSENSITIVE执行,没有调用refreshRow,因此您可以看到常量数据从最初的查询开始,甚至是切换窗口。您可以直接调用refreshRow来查看相同的效果。

从技术上讲,该功能是使用两个游标实现的。第一个对应于所使用的查询,只添加了ROWID列。

select rowid as "__Oracle_JDBC_internal_ROWID__", id, val from test
where  id between :1  and :2   order by id

在每个窗口开关上调用的第二个光标(即,对于提取的每行,提取大小=1)简单外部将保存的rowid与来自第一个光标的查询连接起来,以重新提取当前数据。

WITH "__JDBC_ROWIDS__" AS (SELECT COLUMN_VALUE ID, ROWNUM NUM FROM TABLE(:1 ))
SELECT "__JDBC_ORIGINAL__".*
FROM (select rowid as "__Oracle_JDBC_internal_ROWID__", id, val from test
where  id between :2  and :3   order by id) "__JDBC_ORIGINAL__", "__JDBC_ROWIDS__"
WHERE "__JDBC_ORIGINAL__"."__Oracle_JDBC_internal_ROWID__"(+) = "__JDBC_ROWIDS__".ID
ORDER BY "__JDBC_ROWIDS__".NUM 

也有类似的问题,但没有一个真正解释这个问题,所以我不把这个问题标记为重复的:

ResultSet.TYPE_SCROLL_SENSITIVE 的行为

JDBC结果集类型_滚动_敏感

JDBC结果集类型滚动敏感

简短的答案是,您使用的默认获取大小过高,以观察单行的更新

测试于Oracle Database 12c Enterprise Edition Release 12.2.0.1.0DriverVersion 12.2.0.1.0

最新更新