У меня есть эти сущности
class Foo{
Set<Bar> bars;
}
class Bar{
Foo parent;
String localIdentifier;
}
С этим отображением (извините, аннотаций нет, я старомоден):
<class name="Foo">
...
<set name="bars" cascade="all-delete-orphan" lazy="false" inverse="true">
<key>...</key>
<one-to-many class="Bar"/>
</set>
</class>
<class name="Bar">
...
<property name="localIdentifier" column="local_identifier"/>
<many-to-one name="parent" column="parent_id" />
</class>
У меня также есть уникальное ограничение на 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);
Теперь, по какой-то причине, Hibernate не выполняет вещи в порядке их вызова. Он не выполняет clear()
(удаление) перед add()
(вставка), а наоборот, сначала пытается вставить, получая ConstraintViolationException
Я знаю, что добавление небольшого числа session.flush()
после bars.clear();
может исправить это, но в этом случае у меня нет доступа к сеансу неприглядным способом.
Так что, флеш - единственное решение? или есть версия Hibernate, которая соблюдает порядок действий?
Обновление:
Кстати, разыменование коллекции приведет к HibernateException от https://www.hibernate.org/117.html#A3:
Я получаю HibernateException: не
разыменовывать коллекцию с
cascade = "all-delete-orphan" Это
произойдет, если вы загрузите объект с
каскад = "все-удалить-сирота"
коллекция, а затем удалить
ссылка на коллекцию. не
замени эту коллекцию, используй clear ()
поэтому алгоритм удаления сирот может
обнаружить ваши изменения.