Обходной путь для Spring / Hibernate из-за нестандартного поведения ограничения UNIQUE в MS SQL

Существует ограничение базы данных UNIQUE для индекса, которое не позволяет более одной записи иметь одинаковые столбцы.

Есть фрагмент кода, управляемый Hibernate (v2.1.8), выполняющий два вызова DAO
getHibernateTemplate().save( theObject )
, в результате чего в указанную выше таблицу вводятся две записи.

Если этот код выполняется без транзакций, он приводит к INSERT, UPDATE, затем к другим SQL-операторам INSERT и еще одному UPDATE и работает нормально. Очевидно, последовательность состоит в том, чтобы сначала вставить запись, содержащую DB NULL, а затем обновить ее соответствующими данными.

Если этот код выполняется в Spring (v2.0.5), заключенный в одну транзакцию Spring, он приводит к двум INSERTS, за которыми следует немедленное исключение из-за ограничения UNIQUE, упомянутого выше.

Эта проблема проявляется только в MS SQL из-за его несовместимости. с ANSI SQL. Он отлично работает с MySQL и Oracle. К сожалению, наше решение кроссплатформенное и должно поддерживать все базы данных.

Какой способ решения данной проблемы вы бы предпочли, имея этот стек технологий?


person mindas    schedule 25.09.2008    source источник
comment
Из любопытства, какое поведение ANSI SQL определяет в этом случае? Кажется, что вставка двух идентичных строк в таблицу с уникальным ограничением приведет к нарушению ограничения.   -  person Brannon    schedule 26.09.2008
comment
Поведение ANSI заключается в том, что NULL = NULL не соответствует действительности, поэтому в ограничении уникальности должно быть разрешено два значения NULL.   -  person Giacomo Degli Esposti    schedule 26.09.2008


Ответы (2)


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

Кроме того, когда вы говорите, что спящий режим вставляет NULL с помощью вставки, вы имеете в виду, что каждый столбец имеет значение NULL или только столбец идентификатора?

person skaffman    schedule 28.09.2008

У меня нет опыта работы с Hibernate, поэтому я не знаю, можете ли вы изменить БД по своему желанию или для Hibernate требуется определенная структура БД, которую вы не можете изменить.

Если вы можете внести изменения, вы можете использовать этот обходной путь в MSSQL для эмуляции поведения ANSI:

удалить уникальный индекс / ограничение

определите поле calc следующим образом:

alter table MyTable Add MyCalcField as 
case when MyUniqueField is NULL 
      then cast(Myprimarykey as MyUniqueFieldType) 
      else MyUniqueField end

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

Естественно, это применимо, если MyUniqueField не является первичным ключом! :)

Более подробную информацию можно найти в этой статье на databasejournal.com

person Giacomo Degli Esposti    schedule 26.09.2008