Заставить Hibernate выдавать DELETE перед INSERT, чтобы избежать нарушений уникальных ограничений?

Справочная информация: http://jeffkemponoracle.com/2011/03/11/handling-unique-constraint-violations-by-hibernate

Наша таблица:

BOND_PAYMENTS (BOND_PAYMENT_ID, BOND_NUMBER, PAYMENT_ID)

Существует ограничение первичного ключа для BOND_PAYMENT_ID и ограничение уникальности для (BOND_NUMBER, PAYMENT_ID).

Приложение использует Hibernate и позволяет пользователю просматривать все платежи, связанные с конкретным Бонд; и это позволяет им создавать новые ссылки и удалять существующие ссылки. После того, как они внесли все желаемые изменения на странице, они нажимают «Сохранить», и Hibernate делает свое волшебство, чтобы запустить требуемый SQL в базе данных. Судя по всему, Hibernate определяет, какие записи нужно удалить, какие вставить, а остальные оставляет нетронутыми. К сожалению, сначала он выполняет INSERT, а затем DELETE.

Если пользователь удаляет ссылку на платеж, а затем передумает и повторно вставляет ссылку на тот же платеж, Hibernate с радостью пытается вставить ее, а затем удалить. Поскольку эти вставки / удаления выполняются как отдельные операторы SQL, Oracle немедленно проверяет ограничение при первой вставке и выдает нарушение уникального ограничения ORA-00001 .

Нам известны только два варианта:

  1. Сделать ограничение deferrable
  2. Удалить уникальное ограничение

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

ALTER TABLE bond_payments ADD
  CONSTRAINT bond_payment_uk UNIQUE (bond_number, payment_id)
  DEFERRABLE INITIALLY DEFERRED;

Обратной стороной является то, что индекс, созданный для контроля этого ограничения, теперь является неуникальным индексом, поэтому может быть несколько менее эффективным для запросов. Мы решили, что это не такой уж большой ущерб для данного конкретного случая. Другой недостаток (по совету Гэри) заключается в том, что оно может страдать от конкретной ошибки Oracle - хотя я считаю, что мы будем невосприимчивы (по крайней мере, в основном) из-за того, как работает приложение.

Есть ли другие варианты, которые мы должны рассмотреть ?

6
задан OMG Ponies 25 April 2011 в 15:56
поделиться