Поведение ResultSet.TYPE_SCROLL_SENSITIVE - PullRequest
7 голосов
/ 19 января 2010

Я запутался в поведении 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"));
}

Ответы [ 2 ]

13 голосов
/ 19 января 2010

Я что-то здесь неправильно понимаю?

Да. Вы должны получить снова, чтобы получить последнее состояние таблицы, либо запустив SELECT самостоятельно, либо вызвав ResultSet.refreshRow(). Кроме того, прочитайте документы ResultSet.refreshRow() перед его использованием, иначе вы можете получить неожиданные результаты.

Документы, касающиеся TYPE_SCROLL_SENSITIVE,

TYPE_SCROLL_SENSITIVE

Константа, указывающая тип для ResultSet объект с возможностью прокрутки и вообще чувствителен к изменениям сделанные другими.

Это просто означает, что он будет чувствителен к изменениям, внесенным другими в тот же объект ResultSet. Чтобы понять концепцию, я бы посоветовал взглянуть на это официальное Руководство по JDBC: обновление таблиц .

Хорошо, редактирую мой пост, чтобы включить в него конкретную строку из исходного урока,

С помощью прокручиваемого набора результатов вы можете перейти к строкам, которые вы хотите изменить, и если тип TYPE_SCROLL_SENSITIVE, Вы можете получить новое значение в ряд после того, как вы изменили его.

5 голосов
/ 30 августа 2014

Я думаю, что вы используете mysql в качестве базы данных, и это известная ошибка.

Позвольте мне подробно рассказать -

Согласно документации Oracle на сайте java, для 2 используется TYPE_SCROLL_SENSITIVE.цели-

1. Драйвер MySQL теперь может перемещать указатель результирующего набора jdbc туда и обратно (который в противном случае просто идет в прямом направлении), поэтому в основном прокрутка включена {так что теперь вы можете делать resultset.previous ()и указатель вернется назад}

2.Для отображения обновленных значений (внутренних изменений), внесенных в базу данных.

Вы застряли во 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");

для проверки данных: выведите setFetchSize из resultSet, если он переходит от оператора к resultSet, пока Sysout не сохранил конфигурацию выборки, как:

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

, если sysout выдает '1'в качестве размера выборки вы увидите ваши динамические обновления из программы такими, какие они есть, но если он дает «0», это означает, что ваша БД не поддерживает динамическую инициализацию fetchSize ();

Вот проблема с mysql, mysql по умолчанию извлекает все количество строк в ResultSet, и, таким образом, динамическое внутреннее обновление не извлекает динамические значения.(внутреннее обновление - это обновление, выполненное другим потоком той же программы).

Вот ошибка, подтверждающая мою точку зрения на ошибки SQL:

Ошибки SQL. fetchSize Bug

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

orcale docs 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 ();
      }
     }
...