Обновлять более одной строки атомарно

Мне нужно выполнить выбор, а затем обновить некоторые строки в ResultSet атомарным способом.

Код, который я использую, выглядит (упрощенно):

stmt = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
rs = stmt.executeQuery("SELECT ...");

while (rs.next()) {
    if (conditions_to_update) {
        rs.updateString(...);
        rs.updateRow();
    }
}
  • Могу ли я гарантировать, что обновления будут выполняться автоматически? Если нет, то как я могу в этом убедиться?
  • Что произойдет, если какой-либо другой процесс изменил строку базы данных, которую вы обновляете через updateRow()? Есть ли способ заблокировать строки в ResultSet?
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
4
0
1 169
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Используйте транзакции.

Ответ принят как подходящий

Вероятно, здесь вступает в игру целая куча технологий и концепций, и все начинает становиться довольно липким, когда вы начинаете рассматривать многопоточные / многопоточные приложения.

Как заявил Яссевк, вам следует изучить возможность использования Сделки, чтобы гарантировать атомарный характер ваших обновлений - очень низкоуровневым примером было бы сделать что-то вроде:

...
con.setAutoCommit(false);
try {
  while (rs.next()) {
    if (conditions_to_update) {
      rs.updateString(...);
      rs.updateRow();
    }
  }
  con.setAutoCommit(true);
} catch (Exception ex) {
  //log the exception and rollback
  con.rollback();
} finally {
  con.close();
}

Затем все обновления будут объединены в одну транзакцию. Если какое-либо из обновлений сгенерировало исключение (например, недопустимое значение или сбой соединения на этапе выполнения), весь пакет будет отменен. (Наконец добавлено, потому что я его сторонник; p)

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

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

Более сложный подход состоит в том, чтобы гарантировать, что методы для выполнения этих обновлений реализованы потокобезопасным способом. С этой целью:

  • Все обновления для этой таблицы проходят через один класс
  • Этот класс реализует шаблон Singleton или предоставляет методы обновления как статические методы.
  • В методах обновления используется ключевое слово Синхронизировано для предотвращения состояний гонки.

Спасибо. Я искал способ заблокировать таблицу, конкретную строку или даже одну ячейку с помощью JDBC (или, по крайней мере, стандартного SQL). Полагаю, это невозможно.

Guido 17.10.2008 22:09

What happens if any other process has changed the database row that you are updating via updateRow() ? Is there any way to lock the rows in the ResultSet ?

В Oracle вы можете пометить определенные строки для обновления, выполнив следующий SQL.

select cola, colB from tabA for update;

Следующая транзакция / поток / приложение, которое пытается обновить эту строку, получит исключение. см. это для более подробной информации - http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:4530093713805

Другие вопросы по теме