У меня есть эти объекты
class Foo{
Set bars;
}
class Bar{
Foo parent;
String localIdentifier;
}
С этим отображением (извините, никакие аннотации, я старомоден):
...
...
...
У меня также есть ограничение на уникальность данных на 2 столбца: local_identifier
и parent_id
(не уникальное ограничивает на каждом, а уникальный сингл ограничивают содержащий обоих, например, строки № 2 с тем же родителем и тем же localIdentifier позволяются),
alter table bar add constraint unique_bar unique (parent_id, local_identifier)
И этот код, который использует их:
//foo is persistent, foo id = 1
Bars bars = foo.getBars();
bars.clear(); // bars contained 1 item [parent_id = 1, local_identifier = "a"]
Bar newBar = new Bar();
newBar.setParent(foo);
newBar.setLocalIdentifier("a");
bars.add(newBar);
Теперь, по некоторым причинам, Будьте в спящем режиме, не выполняет вещи в порядке, которым их назвали. Это не выполняется clear()
(удалите) перед add()
(вставьте), но наоборот, это сначала пытается вставить, добираясь a ConstraintViolationException
Я знаю добавление немного session.flush()
после bars.clear();
, мог зафиксировать это, но в этом случае, у меня нет доступа к сессии не ужасным способом.
Так сброс, единственное решение? или есть ли Быть в спящем режиме версия, которая уважает порядок действий?
Обновление: Между прочим, разыменование набора приведет к HibernateException от https://www.hibernate.org/117.html#A3:
Я получаю HibernateException: не разыменовывайте набор с каскадом = "all-delete-orphan", Это произойдет, если Вы загрузите объект каскадом = "all-delete-orphan" набор и затем удалите ссылку на набор. Не заменяйте этот набор, используйте ясный (), таким образом, алгоритм удаления висячей строки может обнаружить Ваше изменение.
Полагаю, что смыванию
нет альтернативы здесь :
Спячка нарушает уникальное ограничение!
Спячка - это не совсем то. умный с уникальными ограничениями с инородными ключами. Иногда вы может понадобиться намекнуть.
Уникальное нарушение ограничений может происходит, если два объекта обновлённый, один из них - "высвобождение" значения а другой "получает" то же самое Значение. Обходной путь - flush() значение параметра сессия вручную после обновления первый объект и перед обновлением во-вторых.
(Такого рода проблемы редко встречаются в практика.)
Если вы хотите избежать промывки сеанса здесь, попробуйте заменить весь список ( новый список
вместо Clear ()
). Hibernate должен фактически удалить все элементы в один выстрел, прежде чем добавлять новые. Просто попробуйте, не уверен, работает ли это.
Если вы используете Oracle, вы также можете использовать отсрочные ограничения для откладывания проверки ограничений до тех пор, пока транзакция не будет совершена. Не уверен, если / как это поддерживается другими базами данных.