JPA не планирует удаление сирот и полиморфных коллекций - PullRequest
0 голосов
/ 07 мая 2018

Пожалуйста, посмотрите на код.

    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 не работает с полиморфными коллекциями? Или это я?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...