9

ResultSet我对 type的行为感到困惑TYPE_SCROLL_SENSITIVE

我对此的理解是:

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

2 回答 2

13

我在这里误解了什么吗?

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

文档状态关于 TYPE_SCROLL_SENSITIVE,

TYPE_SCROLL_SENSITIVE

该常量指示 ResultSet 对象的类型,该对象可滚动并且通常对其他人所做的更改很敏感。

这仅仅意味着它会对其他人在同一个 ResultSet 对象中所做的更改敏感。为了理解这个概念,我建议看一下这个官方的JDBC 教程:更新表

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

使用可滚动的结果集,您可以移动到要更改的行,如果类型为 TYPE_SCROLL_SENSITIVE,则可以在更改后的行中获取新值。

于 2010-01-19T08:32:58.373 回答
5

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

让我详细说明-

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

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

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

你被困在第二点...

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

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

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

为了显式定义要获取的行数(例如,将 oracle 的行数从 10 更改为 1),您可以在创建语句时显式定义 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 时从语句传递到 resultSet,则获取配置已保存,如:

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

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

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

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

sql 错误 fetchSize 错误

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

orcale 文档 TYPE_SCROLL_SENSITIVE 示例 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-08-30T17:29:42.440 回答