ResultSet.TYPE_SCROLL_SENSITIVE的行为

div*_*eep 7 java jdbc resultset

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

我对此的理解是:

  1. 我执行一个select查询,返回一个结果集.我打印出第一行中特定列的值.
  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"));
}
Run Code Online (Sandbox Code Playgroud)

Ade*_*ari 13

我在这里误解了什么吗?

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

关于TYPE_SCROLL_SENSITIVE的doc状态,

TYPE_SCROLL_SENSITIVE

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

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

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

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


bon*_*dkn 5

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

让我详细说明一下-

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

1.Mysql驱动程序现在可以将jdbc结果集的指针来回移动(否则只会向前移动),因此基本上启用了滚动功能(所以现在您可以执行resultet.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);
Run Code Online (Sandbox Code Playgroud)

添加一行为:

stmt.setFetchSize(1); //1 is the no. of rows that will be fetched.
Run Code Online (Sandbox Code Playgroud)

将resultSet创建为:

ResultSet rset = stmt.executeQuery("select * from persons");
Run Code Online (Sandbox Code Playgroud)

验证数据:从resultSet打印setFetchSize,如果它已在Sysout中从语句传递到resultSet,而保存的取回配置为:

System.out.println("fetch size: " + resultSet.getFetchSize());
Run Code Online (Sandbox Code Playgroud)

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

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

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

sql错误fetchSize错误

if you use oracle,this java doc copied from oracle documentation will just work fine:
Run Code Online (Sandbox Code Playgroud)

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 ();
      }
     }
Run Code Online (Sandbox Code Playgroud)