我有与这3个实体映射的n-n关系:
@Entity
public class ApplicatifDo {
.....
@OneToMany(cascade = CascadeType.ALL, mappedBy = "applicatifDo", fetch = FetchType.EAGER, orphanRemoval = true)
private Set<ApplicatifTerminalDo> applicatifTerminalSet;
.....
}
@Entity
public class ApplicatifTerminalDo {
......
@ManyToOne
@JoinColumn(name = "idApplicatif", nullable = false)
private ApplicatifDo applicatifDo;
@ManyToOne
@JoinColumn(name = "idTerminal", nullable = false)
private TerminalDo terminalDo;
@Column
private String remarques;
......
}
@Entity
public class TerminalDo {
......
@OneToMany(cascade = CascadeType.ALL, mappedBy = "terminalDo", fetch = FetchType.EAGER, orphanRemoval = true)
private Set<ApplicatifTerminalDo> applicatifTerminalSet;
......
}
我尝试进行测试,其中我有一个ApplicatifDo持久化,其中包含许多ApplicatifTerminalDo,并且我更改了这些的一些值,删除其他值,在此集合中添加新的:
modifyRemarques(firstElement(applicatifDo.getApplicatifTerminalSet()));
applicatifDo.getApplicatifTerminalSet.add(anotherApplicatifTerminal);
applicatifDo.getApplicatifTerminalSet.remove(onceApplicatifTerminal);
然后当我合并时,在我的数据库中,在我的连接表ApplicatifTerminal中,我看到出现了“Remarques”的修改,以及出现的新ApplicatifTerminal实体,但删除没有工作,应该删除的实体仍然存在于我的连接表中(我使用orphanRemoval)。
当我测试时,我在控制台中没有出现任何错误,但是删除实体仍然不应该在DB中。
PS:我在1-n关系上使用了相同的方法,并且父实体中包含的实体集上的所有类型修改的级联都运行良好(包括删除)。
更新:
我试图从ChrisDo中删除OnceApplicatifTerminal,但仍然无法正常工作。这是代码:
Iterator<ApplicatifTerminalDo> iterator = applicatifDo
.getApplicatifTerminalSet().iterator();
boolean first = true;
while (iterator.hasNext()) {
ApplicatifTerminalDo element = iterator.next();
if (!first) {
element.setRemarques("remarques updated");
} else {
iterator.remove();
element.getTerminalDo().setApplicatifTerminalSet(
applicatifDo.getApplicatifTerminalSet());
first = false;
}
}
在这里,我尝试从列表中删除第一个ApplicatifTerminalDo,并为其他人更新列值。当我合并时,值会被更改,但删除不起作用,即使我让TerminalDo删除了更新的ApplicatfTerminal Set。
有可能实现我想做的事吗? 从个人联接表中更新/删除行的最佳做法是什么?
请帮助,我不明白为什么。
答案 0 :(得分:0)
您期望孤儿删除能够启动,因为您已取消引用OnceApplicatifTerminal,并希望OnceApplicatifTerminal。
Orphan删除有一些缺点,当它在其他ORM中称为私有所有权时会暗示:实体实际上应该只是私有,这不是这里的情况。当您调用applicatifDo.getApplicatifTerminalSet.remove(onceApplicatifTerminal);
时遇到问题,因为存在一个也引用此onceApplicatifTerminal实例的TerminalDo实例。 JPA允许使用缓存,因此除非在您的实体中清除此TerminalDo-&gt; onceApplicatifTerminal,否则会留下对onceApplicatifTerminal实体的引用,并且由于您的级联Persist / Merge设置,这会导致它复活。只需删除TerminalDo-&gt; ApplicatifTerminalDo上的级联设置,就好像未删除引用一样,缓存仍将保留引用此不存在的实体。
应谨慎使用孤立删除,并且仅适用于其他实体未引用引用实体的关系,或者需要注意事先清理这些引用。