3.2.1.4.2. Политика обработки связей
Для мягко удаляемых сущностей, платформа предоставляет средство обработки связей при удалении экземпляров, во многом аналогичное правилам ON DELETE внешних ключей в базе данных. Это средство работает на уровне Middleware и использует аннотации @OnDelete, @OnDeleteInverse атрибутов сущности.
Аннотация @OnDelete обрабатывается при удалении той сущности, в которой она встретилась, а не той, на которую указывает аннотированный атрибут (в этом отличие от каскадных удалений на уровне БД).
Аннотация @OnDeleteInverse обрабатывается при удалении той сущности, на которую указывает аннотированный атрибут, (т.е. аналогично каскадному удалению на уровне внешних ключей в БД). Эта аннотация полезна при отсутствии в удаляемом объекте атрибута, который нужно проверять при удалении. При этом, как правило, в проверяемом объекте существует ссылка на удаляемый, на этот атрибут и устанавливается аннотация @OnDeleteInverse.
Значением аннотации может быть:
-  DeletePolicy.DENY- запретить удаление сущности, если аннотированный атрибут неnullили не пустая коллекция
-  DeletePolicy.CASCADE- каскадно удалить аннотированный атрибут
-  DeletePolicy.UNLINK- разорвать связь с аннотированным атрибутом. Разрыв связи имеет смысл указывать только на ведущей стороне ассоциации - той, которая в классе сущности аннотирована@JoinColumn.
Примеры:
-  Запрет удаления при наличии ссылки: при попытке удаления экземпляра Customer, на который ссылается хотя бы одинOrder, будет выброшено исключениеDeletePolicyException.Order.java@ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "CUSTOMER_ID") @OnDeleteInverse(DeletePolicy.DENY) protected Customer customer;Customer.java@OneToMany(mappedBy = "customer") protected List<Order> orders;Сообщения в окне исключения могут быть локализованы в главном пакете сообщений. Используйте для этого следующие ключи: -  deletePolicy.caption- заголовок уведомления.
-  deletePolicy.references.message- тело сообщения.
-  deletePolicy.caption.sales_Customer- заголовок уведомления для конкретной сущности.
-  deletePolicy.references.message.sales_Customer- тело сообщения для конкретной сущности.
 
-  
-  Каскадное удаление элементов коллекции: при удалении экземпляра Roleвсе экземплярыPermissionтакже будут удалены.Role.java@OneToMany(mappedBy = "role") @OnDelete(DeletePolicy.CASCADE) protected Set<Permission> permissions;Permission.java@ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "ROLE_ID") protected Role role;
-  Разрыв связи с элементами коллекции: удаление экземпляра Roleприведет к установке вnullссылок со стороны всех входивших в коллекцию экземпляровPermission.Role.java@OneToMany(mappedBy = "role") protected Set<Permission> permissions;Permission.java@ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "ROLE_ID") @OnDeleteInverse(DeletePolicy.UNLINK) protected Role role;
Особенности реализации:
-  Политика обработки связей обрабатывается на уровне Middleware при сохранении сущностей, реализующих интерфейс SoftDelete, в БД.
-  Нужно быть осторожным при использовании @OnDeleteInverseс политикамиCASCADEиUNLINK, так как при этом происходит извлечение из БД на сервер приложения всех экземпляров ссылающихся объектов, изменение и затем сохранение.Например, в случае ассоциации Customer-Jobи большого количества работ для одного заказчика, если поставить на атрибутJob.customerполитику@OnDeleteInverse(CASCADE), то при удалении экземпляра заказчика будет предпринята попытка извлечь и изменить все его работы. Это может привести к перегрузке сервера приложения и БД.С другой стороны, использование @OnDeleteInverse(DENY)безопасно, так как при этом производится только подсчет количества ссылающихся объектов, и если оно больше0, выбрасывается исключение. Поэтому@OnDeleteInverse(DENY)для атрибутаJob.customerвполне допустимо.