Hibernate одновременная вставка - PullRequest
9 голосов
/ 17 мая 2011

Я столкнулся с проблемой. У меня есть приложение с Hibernate, который загружает данные из файлов XML в таблицы в параллельном режиме. Некоторая часть данных может быть одинаковой и может быть вставлена ​​из разных потоков. Каждый поток работает в своей собственной лонг-плей транзакции. Существует проблема, когда два или более протектора пытаются совершить транзакцию. Например, два потока вставили записи в таблицу Город , которая имеет ограничение на поле ИМЯ . Это означает, что ConstraintViolationException возникает в flush () или commit (). Я хочу автоматически обрабатывать эти коллизии и хочу, чтобы новые проблемные объекты были заменены на старые уже вставленные объекты. Это возможно? Я смотрю на saveOrUpdate () и оптимистичный контроль версий в Hibernate.

Ответы [ 3 ]

1 голос
/ 17 мая 2011

Я предполагаю, что вы используете одну из СУБД на базе MVCC .

Если уровень изоляции транзакции не выше READ COMMITTED, вы можете уменьшить вероятность конфликта, выполнив запрос для проверки существования городов с тем же name, прежде чем вставлять новый.

Обратите внимание, что saveOrUpdate() здесь не может помочь, поскольку name не является первичным ключом. Также обратите внимание, что вы не можете предотвратить конфликт вообще (по крайней мере, без использования некоторых специфических для СУБД функций), поскольку в основном это пример аномалии записи , который не может быть предотвращен в СУБД на основе MVCC.

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

0 голосов
/ 10 мая 2018

Распределение входных данных по потокам в соответствии с названием города.

0 голосов
/ 14 ноября 2011

В подобных ситуациях мы используем соглашение метода 'insertOrUpdate ()' со следующим общим потоком. Транзакция фиксируется вызывающей стороной метода insertOrUpdate () по возвращении:

public MyHibernateObject insertOrUpdate(MyHibernateObject newObj, Session s) {
    String name = newObj.getCityName();
    MyHibernateObject existingObj = getByCityName(name, s);
    if ( existingObj == null ) {
        s.saveOrUpdate(newObj);
        return newObj;
    } else {
        existing.copyImportantFields(newObj);
        s.saveOrUpdate(existing);
        return existing;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...