Как удалить детей-сирот при сохранении родителя
Вкратце ситуация следующая
У меня есть документ, в документе много полей разных типов. Одно из этих полей имеет тип авторизации, который принимает список действий авторизатора. Мне нужно, чтобы при обновлении документа и изменении списка действий авторизатора старые действия авторизатора успешно удалялись из БД.
class Document {
@OneToMany(mappedBy = "_field", fetch = FetchType.LAZY, cascade = {
CascadeType.PERSIST, CascadeType.REMOVE, CascadeType.MERGE, CascadeType.DETACH})
private final SortedSet<Field<?>> _fields = new TreeSet<>();
}
class Field<T> {
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "document_id", nullable = false)
private Document _document;
@OneToMany(mappedBy = "_documentField", fetch = FetchType.LAZY, cascade = CascadeType.ALL,
orphanRemoval=true )
private SortedSet<AuthorizerAction> _authorizers;
}
class AuthorizerAction {
@ManyToOne(fetch = FetchType.LAZY, cascade = { CascadeType.MERGE, CascadeType.REFRESH } )
@JoinColumn(name = "field_id", nullable = false)
private Field<FiledAuthType> _documentField;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User _authorizer;
}
Но какие бы изменения я ни применял, у меня возникают разные проблемы, или они просто не работают должным образом, и я не могу найти элегантное решение без ручного удаления авторизаторов из БД.
Предположим, я получаю объект Document из БД со всеми его зависимостями. Я меняю список AuthorizerActions, и когда я сохраняю объект документа, я использую
_documentDao.save(document);
После сохранения запускается удаление сирот, но происходит сбой с ошибкой, что объект уже отсоединен.
- В некоторых случаях потерянные элементы успешно удаляются, в основном при обновлении объекта AuthorizerActions.
- В других случаях ошибка не выдается, но потерянные файлы не удаляются из БД, и
- В некоторых случаях выдается такая ошибка.
Caused by: java.lang.IllegalArgumentException: Removing a detached instance com.test.document.domain.AuthorizerAction#6
at org.hibernate.jpa.event.internal.core.JpaDeleteEventListener.performDetachedEntityDeletionCheck(JpaDeleteEventListener.java:52)
at org.hibernate.event.internal.DefaultDeleteEventListener.onDelete(DefaultDeleteEventListener.java:89)
at org.hibernate.internal.SessionImpl.fireDelete(SessionImpl.java:1013)
at org.hibernate.internal.SessionImpl.delete(SessionImpl.java:943)
at org.hibernate.engine.internal.Cascade.deleteOrphans(Cascade.java:553)
at org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:526)
at org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:423)
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:386)
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:193)
at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:126)
at org.hibernate.event.internal.AbstractSaveEventListener.cascadeAfterSave(AbstractSaveEventListener.java:445)
at org.hibernate.event.internal.DefaultPersistEventListener.justCascade(DefaultPersistEventListener.java:172)
Не могли бы вы помочь мне понять, где я ошибаюсь?