在理解Java JDBC ResultSet类型时,有两种滚动类型TYPE_SCROLL_SENSITIVE和TYPE_SCROLL_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");
}
}
}
当程序到达LINE 39时,我将从后端更新数据库以进行记录。对于TYPE_SCROLL_INSENSITIVE,它不显示应执行的更新记录,但对于TYPE_SCROLL_SENSITIVE,则未执行所需的行为。它必须显示更新的记录,但不显示。谁能说出为什么呢?
我在googled处(不是Java doc或JLS)读到ODBC瘦驱动程序,OCI驱动程序支持INSENSITIVE ResultSet对象并且不敏感的某个地方。是这样吗?如果是,为什么,哪个驱动程序同时支持两者?如果否,那么我要去哪里错了。
我经过了link,但没有指出我的问题。任何建议将不胜感激。
编辑:添加了这些行以检查支持
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}-> true
{TYPE_SCROLL_SENSITIVE,CONCUR_UPDATABLE}-> true
{TYPE_SCROLL_SENSITIVE,CONCUR_READ_ONLY}-> true
最佳答案
与其他不起作用的功能一样,使用它们之前必须先阅读documentation。
重要的是窗口的概念
滚动敏感结果集的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
从数据库获取当前值。
请注意,此行为仅对
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
那里有类似的问题,但是没有一个真正说明问题,所以我不将此问题标记为重复:
Behaviour of ResultSet.TYPE_SCROLL_SENSITIVE
JDBC ResultSet Type_Scroll_Sensitive
JDBC result set type scroll sensitive
简短的答案是,您使用的默认访存大小过高,以观察单行的更新。
测试完成于
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0
DriverVersion 12.2.0.1.0
关于java - JDBC类型滚动不敏感和敏感,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54553339/