Пожалуйста, посмотрите на код.
for (CowRow row : entity.getCowRows()) {
em.remove(row.getCowRowData());
em.remove(row);
}
entity.getCowRows().clear();
Где
@Entity
@Table(name = "cowrow")
public class CowRow {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
private Cow cow;
private int rowNumber;
@OneToOne(mappedBy = "cowRow", cascade = CascadeType.ALL, orphanRemoval = true)
private CowRowData cowRowData;
//accessors here
}
CowRowData является родительской сущностью для CowPriceTag и CowReasoning. «Сущность» - это Корова, которая содержит это:
@OneToMany(mappedBy = "cow", orphanRemoval = true)
private Collection<CowRow> cowRows;
При сбросе этот фрагмент кода создает журнал:
2018-05-07 11:20:21.351 TRACE 15892 --- [nio-8080-exec-1] org.hibernate.engine.internal.Cascade : Processing cascade ACTION_PERSIST_ON_FLUSH for: ru.dz.bis.entities.Cow
2018-05-07 11:20:21.353 TRACE 15892 --- [nio-8080-exec-1] org.hibernate.engine.internal.Cascade : Done processing cascade ACTION_PERSIST_ON_FLUSH for: ru.dz.bis.entities.Cow
Есть еще несколько записей о каскадировании, но ни одна из них не касается CowRow или CowRow.
Однако, если я уберу этот цикл for, можно ожидать, что очистка коллекции приведет к удалению потерянных экземпляров CowRow. Однако по какой-то причине удаление происходит не по расписанию с таким странным журналом:
2018-05-07 11:40:49.342 TRACE 19739 --- [nio-8080-exec-3] org.hibernate.engine.internal.Cascade : Processing cascade ACTION_PERSIST_ON_FLUSH for: ru.dz.bis.entities.Cow
2018-05-07 11:40:49.343 TRACE 19739 --- [nio-8080-exec-3] org.hibernate.engine.internal.Cascade : Done processing cascade ACTION_PERSIST_ON_FLUSH for: ru.dz.bis.entities.Cow
2018-05-07 11:40:49.343 TRACE 19739 --- [nio-8080-exec-3] org.hibernate.engine.internal.Cascade : Processing cascade ACTION_PERSIST_ON_FLUSH for: ru.dz.bis.entities.Folder
2018-05-07 11:40:49.344 TRACE 19739 --- [nio-8080-exec-3] org.hibernate.engine.internal.Cascade : Done processing cascade ACTION_PERSIST_ON_FLUSH for: ru.dz.bis.entities.Folder
2018-05-07 11:40:49.345 TRACE 19739 --- [nio-8080-exec-3] org.hibernate.engine.internal.Cascade : Processing cascade ACTION_PERSIST_ON_FLUSH for: ru.dz.bis.entities.CowRow
2018-05-07 11:40:49.346 TRACE 19739 --- [nio-8080-exec-3] o.hibernate.engine.spi.CascadingAction : Cascading to persist on flush: ru.dz.bis.entities.CowRowData
2018-05-07 11:40:49.346 TRACE 19739 --- [nio-8080-exec-3] o.h.e.i.AbstractSaveEventListener : Persistent instance of: ru.dz.bis.entities.CowRowData
2018-05-07 11:40:49.347 TRACE 19739 --- [nio-8080-exec-3] o.h.e.i.DefaultPersistEventListener : Ignoring persistent instance
20
Если orphanRemoval работает, почему JPA сохраняет CowRow? Я очистил Cow.cowRows, JPA должен запланировать удаление этих строк. И нет никаких упоминаний о не планировании в журнале!
Хорошо, давайте попробуем что-нибудь еще. Давайте просто сделаем «em.remove (row.getCowRowData ())» в цикле «для». Теперь я вижу это:
2018-05-07 11:54:26.869 TRACE 22914 --- [nio-8080-exec-1] org.hibernate.engine.internal.Cascade : Processing cascade ACTION_PERSIST_ON_FLUSH for: ru.dz.bis.entities.CowRow
2018-05-07 11:54:26.870 TRACE 22914 --- [nio-8080-exec-1] o.hibernate.engine.spi.CascadingAction : Cascading to persist on flush: ru.dz.bis.entities.CowRowData
2018-05-07 11:54:26.873 TRACE 22914 --- [nio-8080-exec-1] o.h.e.i.AbstractSaveEventListener : Deleted instance of: ru.dz.bis.entities.CowRowData
2018-05-07 11:54:26.878 TRACE 22914 --- [nio-8080-exec-1] o.h.e.i.DefaultPersistEventListener : un-scheduling entity deletion [[ru.dz.bis.entities.CowPriceTag#8]]
Итак, 1) существует разница между положением orphanRemoval и выполнением ручного удаления, 2) JPA по какой-то причине является каскадом обработки, сохраняющимся для RowData, 3) при обработке этого каскада, JPA говорит, что удаляет CowRowData (почему сейчас? возможно, из-за orphanRemoval?), 4) и сразу после этого отменяет удаление, например, потому что эти CowRowData ссылаются на CowPriceTag (ОК, но это та же сущность - ее подкласс! и, кроме того, она удалена!)
И только если я выполняю "em.remove (row)" в цикле, код работает как задумано. Хотя даже сейчас не совсем: удаление row.getCowRowData () должно сделать CowRowData бесхозным (в CowRow-> CowRowData) и запланировать его удаление (аналогично CascadeType.REMOVE в данном случае), чего не происходит.
Что все это значит?
Может быть, orphanRemoval не работает с полиморфными коллекциями? Или это я?