hibernate - JPA 不安排删除孤儿和多态集合
问题描述
请看代码。
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 的父实体。“实体”是包含以下内容的 Cow:
@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 应该安排这些行进行删除。并且日志中没有提到取消计划!
好吧,让我们试试别的。让我们在“for”循环中执行“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 不适用于多态集合?还是我?
解决方案
推荐阅读
- sql-server - sql server 游标结果显示不正常?
- java - 循环通过连接四个网格
- razor - Asp.net 在刷新时丢失数字格式
- java - 在 Scala 上验证 SHA1withECDSA 签名
- html - 如何强制一行及其列使用其父元素高度的 100% (jumbotron)
- python-3.x - Peewee - 使用 ForeignKeyField('self') 更新记录问题
- go - 在模板中使用函数而不是方法
- android - MaterialSearchView + 工具栏 + 地图
- python - 即使成功将 selenium 包安装到 pycharm 也无法运行 selenium 脚本
- asp.net - 如何在MVC中将单个对象和列表对象从视图返回到控制器