我有
public class RelationObject {
@OneToMany(orphanRemoval = true, mappedBy = "relationObject")
private Set<RelationParticipant> participants = new HashSet<RelationParticipant>();
}
public class BusinessObject {
@OneToMany(orphanRemoval = true, mappedBy = "businessObject")
private Set<RelationParticipant> participants = new HashSet<RelationParticipant>();
}
和
public class RelationParticipant {
@ManyToOne
@JoinColumn(name = "ro_id", nullable = false)
private RelationObject relationObject;
@ManyToOne
@JoinColumn(name = "bo_id", nullable = false)
private BusinessObject businessObject;
}
我有一个RelationParticipant连接到一个RelationObject(relobj)和一个BusinessObject。 现在我做了em.remove(relobj),并且在提交或刷新时我得到了完整性异常。或者有时我不喜欢,这取决于。
根据JPA规范,&#34;如果将删除操作应用于托管源实体,则删除操作将级联到关系目标&#34;。但有时候这种情况不会发生。有时会这样。为什么呢?
答案 0 :(得分:0)
JPA声明孤立删除操作与关系中的级联删除操作相同,因此不需要设置级联删除 - 当您删除RelationObject时,如果orphanRemoval = true,JPA将删除任何引用的RelationParticipants。
在所有情况下,您可能都不会看到此行为,因为JPA只能将删除级联到它知道的实体。在您的情况下,检查RelationObject的参与者集合是否真正拥有2个在数据库中引用它的RelationParticipants。如果没有,JPA将只删除它知道的那些。一种快速检查方法是在调用remove之前调用RelationObject上的refresh。这在不维护双向关系关系双方的应用程序中很常见,例如,通过设置RelationParticipants-&gt; RelationObject引用而不将RelationParticipants添加到RelationObject的参与者集合中。如果是这种情况,JPA不会为您维护双向关系 - 应用程序需要保持双方自身同步。
答案 1 :(得分:0)
经过几天的研究后,我发现了以下行为。 OrphanRemoval只将cascades移除到成为孤儿的实体;而不只是一个关系的孤儿(其来源被删除),而是所有关系的孤儿。示例:如果我在其Target []中删除包含X的Source,则X将变为孤立,除非有另一个源S,其中X也是目标。当然,当X是S的“主”时,这是很自然的(S包含FK到X);但即使X是S的“子”,X也不会发生级联(X包含FK到S,而X是反向关系的源:“mappedBy = ...”)。 我在JPA规范中找不到这个特殊条件,所以也许我错了?但至少这种解释是有道理的。
因此,在我的示例中,删除relobj不会级联到其RelationParticipants,因为后者的每一个也都由其BusinessObject引用(作为关系的反向非拥有方)。
另一个有趣的行为:如果EntityManager不知道任何障碍,即使在那种情况下也会发生级联CAN STILL。比方说,在DB中有一个引用RelationParticipant的BusinessObject,但它尚未被EntityManager加载。在这种情况下,EntityManager将不会检测此BusinessObject对RelationParticipant的反向引用,并且em.remove(relobj)将成功级联到relobj.getParticipants()。