【问题标题】:Behaviour of ResultSet.TYPE_SCROLL_SENSITIVEResultSet.TYPE_SCROLL_SENSITIVE 的行为
【发布时间】:2011-01-06 16:37:49
【问题描述】:

我对 ResultSet 类型为 TYPE_SCROLL_SENSITIVE 的行为感到困惑。

我对此的理解是:

  1. 我执行了一个返回结果集的选择查询。我打印出第一行中特定列的值。
  2. 然后我执行Thread.sleep(10000),这会使程序暂停 10 秒。
  3. 当程序处于休眠状态时,我手动更新数据库中的同一列(通过 SQL 提示符)。
  4. 10 秒后,我再次打印结果集第一行中同一列的值。

在第 4 步中,我希望打印的列值与第 1 步中打印的值不同。但我总是得到相同的值(即使我的 ResultSetSCROLL_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"));
}

【问题讨论】:

  • 另外,我刚刚注意到JDBC提供了另一种方法“ResultSet.refreshRow()”。将此添加到代码中(就在第 4 步之前)会给我想要的结果。那么TYPE_SCROLL_SENSITIVE有什么用呢?
  • refreshRow() 仅表示向数据库发起查询以获取最新状态。
  • TYPE_SCROLL_SENSITIVE 隐式调用refreshRow。详情见Oracle implementation

标签: java jdbc resultset


【解决方案1】:

我在这里误解了什么吗?

是的。您必须再次获取表的最新状态,方法是自己触发SELECT,或调用ResultSet.refreshRow()。另外,使用前请阅读ResultSet.refreshRow()的文档,否则可能会得到意想不到的结果。

文档说明 TYPE_SCROLL_SENSITIVE,

TYPE_SCROLL_SENSITIVE

表示类型的常量 可滚动的 ResultSet 对象 并且通常对变化敏感 别人做的。

这仅仅意味着它会对其他人在同一个 ResultSet 对象中所做的更改敏感。要理解这个概念,我建议看看这个官方JDBC Tutorial: Updating Tables

好的,编辑我的帖子以包含原始教程中的特定行,

使用可滚动的结果集,您可以 移动到要更改的行,并且 如果类型是 TYPE_SCROLL_SENSITIVE, 可以连续获取新值 修改后。

【讨论】:

  • 我还是不明白:(。“你改完后可以连续获取新值”。这是否意味着如果我执行ResultSet.updateXXX(columnIndex, val),我可以通过执行 ResultSet.getXXX(columnIndex) 获取更新后的值吗?
  • 是的,完全正确。另一个不是TYPE_SCROLL_INSENSITIVE
  • 可能是驱动程序实现问题。不确定。
  • @Adeel Ansari 你能修改我的问题stackoverflow.com/questions/25582698/…
【解决方案2】:

我认为你正在使用 mysql 作为你的数据库,这是一个已知的错误。

让我详细说明-

根据 Java 站点上的 Oracle 文档,TYPE_SCROLL_SENSITIVE 用于 2 个目的-

1.Mysql驱动现在可以来回移动jdbc结果集的指针 (否则只会向前移动),所以基本上启用了滚动 {所以现在你可以执行 resultset.previous() 并且指针会返回}

2.显示更新的值(内部更改),对数据库进行。

你被困在第二点...

看到你的程序不工作了,因为你从来没有使用过 fetchSize() 的概念;

每当使用 jdbc 时,驱动程序都会将默认行数提取到显示的缓存中(例如:oracle 默认加载 10 行)

所以 TYPE_SCROLL_SENSITIVE 将仅显示下一次缓存重新加载的更新值。 就像您在数据库中有 100 行,您更新了所有行,但在那之前只获取了 10 行,因此您将随后打印其他 90 行更新,因为驱动程序将在 9 轮缓存管理中加载这些表。

为了显式定义要获取的行数(例如将行数从 10 更改为 1 用于 oracle),您可以在创建语句时显式定义 fetchSize()。(但在最后无效地使用缓存减慢速度)

所以在初始化语句时:

Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
            ResultSet.CONCUR_UPDATABLE);

添加一行为:

stmt.setFetchSize(1); //1 is the no. of rows that will be fetched.

创建结果集为:

ResultSet rset = stmt.executeQuery("select * from persons");

验证数据:从resultSet打印setFetchSize,如果它在Sysout时从statement传递到resultSet,则获取配置已保存,如:

System.out.println("fetch size: " + resultSet.getFetchSize());

如果 sysout 给出 '1' 作为获取大小,您将看到程序中的动态更新, 但如果它给出 '0' 则意味着您的数据库不支持 fetchSize() 的动态初始化;

这里是mysql的问题,默认情况下mysql会将所有行数提取到ResultSet中,因此动态内部更新,不会提取动态值。 (内部更新是由同一程序的其他线程完成的更新)。

这是支持我对 sql 错误的观点的错误:

sql bugs fetchSize Bug

if you use oracle,this java doc copied from oracle documentation will just work fine:

orcale docs TYPE_SCROLL_SENSITIVE example ResultSet5.java

import java.sql.*;

public class ResultSet5
{
  public static void main(String[] args) throws SQLException
  {
    // Load the Oracle JDBC driver
    DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
    // Connect to the database
    // You can put a database name after the @ sign in the connection URL.
    Connection conn =
    DriverManager.getConnection ("jdbc:oracle:oci8:@", "scott", "tiger");
    // Create a Statement
    Statement stmt = conn.createStatement (ResultSet.TYPE_SCROLL_SENSITIVE, 
                                     ResultSet.CONCUR_UPDATABLE);
    // Set the statement fetch size to 1
    stmt.setFetchSize (1);
    // Query the EMP table
    ResultSet rset = stmt.executeQuery ("select EMPNO, ENAME, SAL from EMP");
    // List the result set's type, concurrency type, ..., etc
    showProperty (rset);


// List the query result 
System.out.println ("List ENO, ENAME and SAL from the EMP table: ");
while (rset.next())
{
  System.out.println (rset.getInt(1)+" "+rset.getString(2)+" "+
                      rset.getInt(3));
}
System.out.println ();

// Do some changes outside the result set
doSomeChanges (conn);

// Place the cursor right before the first row
rset.beforeFirst ();

// List the employee information again
System.out.println ("List ENO, ENAME and SAL again: ");
while (rset.next())
{
  // We expect to see the changes made in "doSomeChanges()"
  System.out.println (rset.getInt(1)+" "+rset.getString(2)+" "+
                      rset.getInt(3));
}

// Close the RseultSet
rset.close();

// Close the Statement
stmt.close();

// Cleanup
cleanup(conn);

// Close the connection
conn.close();   
  }

  /**
   * Update the EMP table.
   */ 
  public static void doSomeChanges (Connection conn)throws SQLException
  {
    System.out.println ("Update the employee salary outside the result set\n");

    Statement otherStmt = conn.createStatement ();
    otherStmt.execute ("update emp set sal = sal + 500");
    otherStmt.execute ("commit");
    otherStmt.close ();
  }

  /**
   * Show the result set properties like type, concurrency type, fetch 
   * size,..., etc.
   */
  public static void showProperty (ResultSet rset) throws SQLException
  {
    // Verify the result set type
switch (rset.getType())
{
  case ResultSet.TYPE_FORWARD_ONLY:
    System.out.println ("Result set type: TYPE_FORWARD_ONLY");
    break;
  case ResultSet.TYPE_SCROLL_INSENSITIVE:
    System.out.println ("Result set type: TYPE_SCROLL_INSENSITIVE");
    break;
  case ResultSet.TYPE_SCROLL_SENSITIVE:
    System.out.println ("Result set type: TYPE_SCROLL_SENSITIVE");
    break;
  default: 
    System.out.println ("Invalid type");
    break;
}

// Verify the result set concurrency
switch (rset.getConcurrency())
{
  case ResultSet.CONCUR_UPDATABLE:
    System.out.println 
               ("Result set concurrency: ResultSet.CONCUR_UPDATABLE");
    break;
  case ResultSet.CONCUR_READ_ONLY:
    System.out.println 
               ("Result set concurrency: ResultSet.CONCUR_READ_ONLY");
    break;
  default: 
    System.out.println ("Invalid type");
    break;
}
// Verify the fetch size
System.out.println ("fetch size: "+rset.getFetchSize ());
System.out.println ();
  }

  /* Generic cleanup.*/
      public static void cleanup (Connection conn) throws SQLException
      {
        Statement stmt = conn.createStatement ();
        stmt.execute ("UPDATE EMP SET SAL = SAL - 500");
        stmt.execute ("COMMIT");
         stmt.close ();
      }
     }

【讨论】:

    猜你喜欢
    • 2014-06-01
    • 2011-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-18
    • 2020-04-08
    • 2011-08-31
    相关资源
    最近更新 更多