Обновление базы данных с использованием подготовленного состояния выберите - PullRequest
1 голос
/ 06 марта 2009

Я выбираю подмножество данных из базы данных MS SQL, используя PreparedStatement. Итерируя по набору результатов, я также хочу обновить строки. На данный момент я использую что-то вроде этого:

prepStatement = con.prepareStatement(
                    selectQuery,
                    ResultSet.TYPE_FORWARD_ONLY,
                    ResultSet.CONCUR_UPDATABLE);


 rs = prepStatement.executeQuery();

while(rs.next){
rs.updateInt("number", 20)
rs.updateRow();
}

База данных обновлена ​​с правильными значениями, но я получаю следующее исключение:

Optimistic concurrency check failed. The row was modified outside of this cursor.

Я его погуглил, но не смог найти помощи по этому вопросу.

Как мне предотвратить это исключение? Или, поскольку программа делает то, что я хочу, могу ли я просто игнорировать это?

Ответы [ 2 ]

2 голосов
/ 06 марта 2009

Запись была изменена между моментом, когда она была извлечена из базы данных (с помощью курсора), и моментом, когда вы пытались сохранить ее обратно. Если столбец number можно безопасно обновлять независимо от остальной части записи или независимо от какого-либо другого процесса, уже установившего для столбца number какое-либо другое значение, у вас может возникнуть соблазн сделать следующее:

con.execute("update table set number = 20 where id=" & rs("id") )

Однако состояние гонки сохраняется , и ваше изменение может быть в свою очередь перезаписано другим процессом.

Лучшая стратегия состоит в том, чтобы игнорировать исключение (запись не была обновлена), возможно, переместить сбойную запись в очередь (в памяти), , затем выполнить второй проход поверх ошибочные записи (переоценка условий в query и обновление при необходимости - добавьте number <> 20 в качестве одного из условий в query, если это не так.) Повторяйте до тех пор, пока больше не произойдет сбой записей. Со временем все записи будут обновлены.

0 голосов
/ 09 июля 2009

Если вы точно знаете, какие строки вы будете обновлять, я бы сделал

  • Установите для AUTOCOMMIT значение OFF
  • УСТАНОВИТЬ уровень ИЗОЛЯЦИИ на СЕРИАЛИЗИРУЕМЫЙ
  • ВЫБРАТЬ строку1, строку1 ИЗ таблицы, ГДЕ НЕКОТОРЫЕ УСЛОВИЯ ДЛЯ ОБНОВЛЕНИЯ
  • ОБНОВЛЕНИЕ строк
  • COMMIT

Это достигается с помощью пессимистической блокировки (и если в вашей БД поддерживается блокировка строк, она должна работать)

...