Будьте в спящем режиме - очистка набора с all-delete-orphan и затем добавлением к нему вызывает ConstraintViolationException

У меня есть эти объекты

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" набор и затем удалите ссылку на набор. Не заменяйте этот набор, используйте ясный (), таким образом, алгоритм удаления висячей строки может обнаружить Ваше изменение.

13
задан Eran Medan 28 June 2013 в 04:13
поделиться

3 ответа

Полагаю, что смыванию

нет альтернативы здесь :

Спячка нарушает уникальное ограничение!

Спячка - это не совсем то. умный с уникальными ограничениями с инородными ключами. Иногда вы может понадобиться намекнуть.

Уникальное нарушение ограничений может происходит, если два объекта обновлённый, один из них - "высвобождение" значения а другой "получает" то же самое Значение. Обходной путь - flush() значение параметра сессия вручную после обновления первый объект и перед обновлением во-вторых.

(Такого рода проблемы редко встречаются в практика.)
8
ответ дан 2 December 2019 в 01:21
поделиться

Если вы хотите избежать промывки сеанса здесь, попробуйте заменить весь список ( новый список () вместо Clear () ). Hibernate должен фактически удалить все элементы в один выстрел, прежде чем добавлять новые. Просто попробуйте, не уверен, работает ли это.

1
ответ дан 2 December 2019 в 01:21
поделиться

Если вы используете Oracle, вы также можете использовать отсрочные ограничения для откладывания проверки ограничений до тех пор, пока транзакция не будет совершена. Не уверен, если / как это поддерживается другими базами данных.

1
ответ дан 2 December 2019 в 01:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: