Как имитировать поведение при использовании Hibernate? - PullRequest
11 голосов
/ 09 сентября 2010

Я пишу приложение, которое синхронизирует объекты из стороннего источника данных в нашу собственную схему с промежуточным этапом преобразования / отображения.Я использую Hibernate для представления и сохранения сущностей в нашей собственной схеме.Проблема, с которой я сталкиваюсь, состоит в том, что у меня есть уникальный многостолбцовый ключ на одной из моих таблиц.Поведение, которое я хотел бы видеть, аналогично upsert: когда Hibernate идет, чтобы сохранить сущность и обнаруживает уникальное нарушение ограничения, он вместо этого выполняет обновление.Мы используем MySQL, который обеспечивает синтаксис INSERT ... ON DUPLICATE KEY UPDATE, но я не уверен, как или можно использовать Hibernate, чтобы использовать его?

Я полагаю, я всегда мог попробоватьвставьте, и если я поймаю исключение, сделайте обновление, но это кажется хакерским и неоптимальным.Какие-нибудь советы по чистому способу сделать это?

Ответы [ 2 ]

7 голосов
/ 09 сентября 2010

Мы используем MySQL, который обеспечивает синтаксис INSERT ... ON DUPLICATE KEY UPDATE, но я не уверен, как или можно использовать Hibernate для его использования?

Похоже, кто-то сделал это , переопределив оператор sql-insert, используемый Hibernate для этой сущности. Если вы не против переносимости (и, возможно, использования хранимой процедуры), посмотрите.

Полагаю, я всегда мог бы попробовать вставить, и если я ловлю исключение, сделаю обновление, но это кажется хакерским и неоптимальным. Любые советы по чистому способу сделать это?

Другой вариант:

  1. выполнить выбор по уникальному ключу
  2. если вы найдете запись, обновите ее
  3. если вы не нашли запись, создайте ее

Но если вы не заблокируете целых таблиц во время процесса, вы можете столкнуться с некоторыми условиями гонки в многопоточной и распределенной среде, и шаг № 3 может потенциально завершиться неудачей. Представьте себе две параллельные темы:

Тема 1:

  • Начало транс
  • выполняет выборку по клавише
  • запись не найдена
  • создать запись
  • 1039 * совершить *

Тема 2:

  • начать транс
  • выполняет выборку по той же клавише
  • запись не найдена
  • создать запись
  • commit ( FAIL! , поскольку поток 1 был быстрее и теперь существует запись с тем же уникальным ключом)

Так что вам все равно придется реализовать какой-нибудь механизм повторных попыток (блокировка всей таблицы (таблиц) не является хорошим вариантом IMO).

3 голосов
/ 29 июля 2012

Условие гонки можно избежать, выбрав «выбрать ... для обновления»

...