Обходной путь для 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. К сожалению, наше решение кроссплатформенное и должно поддерживать все базы данных.

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

Из любопытства, какое поведение ANSI SQL определяет в этом случае? Кажется, что вставка двух одинаковых строк в таблицу с уникальным ограничением приведет к нарушению ограничения.

Brannon 26.09.2008 11:56

Поведение ANSI заключается в том, что NULL = NULL не соответствует действительности, поэтому в ограничении уникальности должно быть разрешено два значения NULL.

Giacomo Degli Esposti 26.09.2008 12:12
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
3
2
1 613
2

Ответы 2

У меня нет опыта работы с 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

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

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

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