Можно ли временно отключить каскадирование для объекта Hibernate?

Для объекта Hibernate/JPA с каскадным набором ALL для связанного объекта:

@Entity
public class Entity {
    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "entity")
    private Set<RelatedEntities> relatedEntities;
}

Можно ли временно отключить каскадирование, например разрешить сохранение сущности без сохранения связанных с ней объектов?


person Steve Chambers    schedule 15.09.2015    source источник
comment
Если вы используете каскадные ограничения, вы можете сохранить Entity без проверки ограничений сразу после этого, используя ограничение DEFERRABLE INITIALLY IMMEDIATE. Но в конце транзакции вы должны сохранить также связанные объекты. Подробнее: stackoverflow.com/questions/5300307/   -  person Mr Jedi    schedule 15.09.2015
comment
Спасибо, но не уверен, как это будет работать, поскольку упомянутая статья относится к ключевому слову SQL, но каскады управляются Hibernate?   -  person Steve Chambers    schedule 15.09.2015
comment
каскады наверняка управляются БД (если вы не используете параметр создания с помощью спящего режима, вы должны их создать), я подозреваю, что спящий режим также может проверять ограничения, если вы добавляете аннотации, но я их не использую. Если вы хотите сохранить объект без связанных объектов, возможно, структура базы данных спроектирована неправильно?   -  person Mr Jedi    schedule 15.09.2015
comment
Может быть, вам следует использовать другую таблицу для отношений?   -  person Mr Jedi    schedule 15.09.2015
comment
Конечно, БД управляет каскадами. Если вы нарушите ограничение базы данных, вы получите, например, ConstraintViolationException или DataIntegrityViolationException.   -  person Mr Jedi    schedule 15.09.2015
comment
Вы можете сделать простые тесты, чтобы проверить это. Создайте Entity1 и Entity2, вставьте Entity2 в Entity1, создайте ограничение без каких-либо действий при удалении. Сохраните Entity2, сохраните Entity1 с Entity2 и попробуйте удалить Entity2.   -  person Mr Jedi    schedule 15.09.2015
comment
@MrJedi Вы говорите о совершенно другом понятии, которое вообще не связано с вопросом.   -  person Dragan Bozanovic    schedule 15.09.2015


Ответы (2)


Нет, это невозможно, и, по крайней мере, по моему скромному мнению, это тоже нехорошо. Когда другие разработчики смотрят на сопоставления и код, который сохраняет/объединяет/удаляет... они ожидают, что каскады будут применены и введут неожиданное поведение, если они проконтролируют, что каскады временно отключены где-то еще для кода, о котором они говорят. изменить.

Однако вы можете сопоставить с той же таблицей новый класс сущностей, который не имеет каскадных полей. Затем просто используйте этот объект в ситуациях, когда вы не хотите применять каскады.

person Dragan Bozanovic    schedule 15.09.2015
comment
Вариант использования немного сложно объяснить, но в основном объект используется в качестве посредника для передачи данных из операции пользовательского интерфейса. В этом случае связанные объекты должны быть реконструированы и сохранены один за другим, а не в обычном случае каскадирования. Второе предложение может быть выполнимым - моя единственная оговорка заключается в том, что это неизбежно приведет к некоторому дублированию, но это можно смягчить путем рефакторинга общих частей в родительский класс. - person Steve Chambers; 15.09.2015

Вы не можете временно отключить каскадирование (по крайней мере, насколько мне известно), но поскольку вы используете Hibernate, вы можете вставить новый объект с помощью HQL

String hqlInsert = "insert into DelinquentAccount (id, name) select c.id, c.name from Customer c where ...";
int createdEntities = s.createQuery( hqlInsert ).executeUpdate();

Всегда существует «ручное» решение, в котором вы запоминаете relatedEntities в переменной для последующего использования и устанавливаете значение null в качестве значения в экземпляре Entity перед его сохранением.

person Predrag Maric    schedule 15.09.2015
comment
Предпочел бы избегать решения HQL, поскольку оно не является безопасным для типов и очень хрупким в отношении изменения сущностей. Ручное решение звучит более многообещающе, если оно работает - не приведет ли установка связанных объектов к null к их удалению, если они присутствуют? - person Steve Chambers; 15.09.2015
comment
Это другой вопрос, чем ваш первоначальный, поскольку речь идет об обновлении существующих объектов вместо вставки новых. Я должен был бы проверить, но поскольку RelatedEntity является владеющей стороной отношения, пока вы не установите null в RelatedEntity#entity, я думаю, все должно быть в порядке. - person Predrag Maric; 15.09.2015
comment
Спасибо, исходный вопрос должен был быть довольно широким для всех каскадных операций. (Persist был просто примером - извините, если я не ясно выразился). - person Steve Chambers; 15.09.2015
comment
Вы правы, при втором прочтении становится ясно, что вы имели в виду все каскадные операции, извините. Я бы сократил ответ до только ручного предложения, если бы прочитал его правильно в первый раз :) - person Predrag Maric; 15.09.2015
comment
Не беспокойтесь, не стесняйтесь делать это сейчас, так как приняли ответ, основанный на предложении руководства. - person Steve Chambers; 15.09.2015
comment
Думая об этом еще раз, я думаю, что не одобряю мое ручное предложение, поскольку оно может работать в тривиальных случаях, но в противном случае вызовет много проблем. Вы можете легко столкнуться с проблемами синхронизации между вашими сущностями и базой данных. HQL может быть чувствителен к изменению сущностей, но он не каскадирует ничего, что вам нужно. Не стесняйтесь не принимать мой ответ. - person Predrag Maric; 15.09.2015