我有父母"和"孩子"休眠实体。
On&#34; Parent&#34;我有Set<Child>
来容纳它的孩子。
当我用新孩子更新父母时,一切正常:儿童是在&#34;孩子&#34;表
但是,当我从父哈希集中删除一个元素并保存时,不会删除数据库中的通信子项。
这是:
关于父母(名为工作流程):
@OneToMany(orphanRemoval=true, cascade = CascadeType.ALL, mappedBy="workflow", fetch = FetchType.EAGER)
private Set<ActivityDB> activities;
On Child(名为Activity)
@ManyToOne
@JoinColumn(name="id_workflow")
@Fetch(FetchMode.JOIN)
private WorkflowDB workflow;
我在会话中处理持久性实例。没有错误提出。似乎工作正常,但数据库上的注册仍然存在。
要进行测试,我加载工作流并执行
workflow.activities.remove( activity_index_x )
然后使用session.update( workflow )
保存工作流程。
但是&#34; activity_index_x&#34;仍然在数据库中,当我重新加载工作流程时,它又恢复了生机。
答案 0 :(得分:1)
这是由未清除子到父引用引起的。由于你映射了两面(并以这种方式配置),Hibernate实际上会查看关系的子端。
解决此问题的最佳方法是,当您从工作流程中删除活动时(以及反向)清除活动的工作流程字段,因此:
class Workflow {
public void remove (Activity a) {
if (this.activities.remove(a)) {
a.setWorkflow(null);
}
}
public void add (Activity a) {
if (this.activities.add(a)) {
a.setWorkflow(this);
}
}
}
主要问题是您希望在关系状态中保持关系的哪一方? 您还可以在工作流上映射关系(不要使用mappedBy属性,但使用JoinTable注释将列保留在子表上),并且只将父工作流映射为只读(insertable = false,updatable = false)活动中的字段。 通过这种方式,工作流可以完全控制哪些活动是其中的一部分,活动仍然可以看到它们所属的工作流程。
class Workflow {
@OneToMany
@JoinTable(...)
private Set<Activity> activities
}
class Activity {
@Column(insertable=false, updatable=false)
private Workflow workflow
}
答案 1 :(得分:1)
请务必查看有关bidirectional association links。
的手册最佳做法包括添加添加/删除子方法:
class WorkflowDB {
public void remove (ActivityDB a) {
if (a != null) {
this.activities.remove(a);
a.setWorkflow(null);
}
}
public void add (ActivityDB a) {
if (a != null) {
this.activities.add(a);
a.setWorkflow(this);
}
}
}
但是因为你使用Set作为一对多方面,你需要特别注意equals and hashcode。最好的方法是使用业务键来检查相等性和哈希码算法,并且永远不要使用equals / hashcode的数据库标识符,尤其是与类似哈希的数据结构(set / map)一起使用。
双向关联管理比单向关联更复杂。如果您确实不需要一对多方,则可以将其删除并替换为查询。这样你就必须只管理多对一方。