休眠 JPA:@OneToMany删除旧的,插入新的而不刷新
实际上,我从未完全理解冬眠中的这种行为。我在一个名为“Parent”的实体中使用@OneToMany关系,其注释如下:
@OneToMany(cascade = {CascadeType.ALL, CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE }, orphanRemoval = true)
@JoinColumn(name = "entity_id", insertable = true, updatable = true, nullable = false)
private List<Child> children;
现在我想在一个事务中执行以下操作:
- 获取父实体
- 循环访问子级列表
- 删除其中一个子项
- 插入新子项
所以,基本上我只是完全取代了其中一个孩子。
就我对这个问题的理解而言,我应该能够做这样的事情:(请注意,这只是一些java伪代码来说明问题)
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void deleteAndAdd(Long parentId, Long childId) {
Parent parent = entityManager.find(parentId);
for (Iterator it = parent.children.iterator(); it.hasNext();) {
Child child = it.next();
if (child.id == childId) {
it.remove();
}
}
Child newChild = new Child();
parent.children.add(newChild);
}
但是,如果新子项具有与旧子项相同的唯一键值,则此操作将失败。因此,基本上,在新子实体持久化之前,旧的子实体似乎没有被正确删除。
如果我在删除旧子项和保留新子项之间添加一个实体Manager.flush(),如下所示:
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void deleteAndAdd(Long parentId, Long childId) {
Parent parent = entityManager.find(parentId);
for (Iterator it = parent.children.iterator(); it.hasNext();) {
Child child = it.next();
if (child.id == childId) {
it.remove();
}
}
entityManager.flush();
Child newChild = new Child();
parent.children.add(newChild);
}
一切都很好。在插入新子项之前,将删除子项,这是应该的。
由于我不想假设休眠混淆了发送到DB的语句的顺序,因此我假设的关于休眠的一定还有其他事情,但事实并非如此。任何想法,为什么后一个例子有效,而第一个没有?
休眠版本是3.5。DB is Mysql InnoDB