PlayFramework(JPA,Hibernate)。两个实体software
< -m:n-> tag
,software
是该关系的所有者。我不使用任何cascading
。
我想删除其中包含一些软件的tag
。
考虑到software
是所有者方,我在我的Tag类中写道:
class Tag {
@Override
public Tag delete() {
for (Software software : this.softwares) {
software.tags.remove(this);
software.save(); // if we delete this, we will have an error - a foreign key constraint fails
}
return super.delete();
}
}
在我添加了行software.save()
之后,它现在运作良好。
问题是:为什么我应该这样做?
我有另一个项目 - 没有Play Framework - 它使用JPA-> Hibernate,我没有必要这样做。那有什么区别?
在this link中,他们也不使用save()。
答案 0 :(得分:1)
您链接到的示例中的代码与您的代码不完全相同。
在你链接的代码中,他们删除了许多元素,但是如果你在下面的评论中读到它们就会说:
// then merge() and flush()
将保存对数据库的更改。他们也从拥有该关系的类中删除。
在您的方案中,您正在删除标记,而所有者是关系的另一端。所以你使用(正确) software.tags.remove 来清理关系。
现在,如果您不保存,实体管理器尚未确认更改,并且当它尝试删除标记时,此实体管理器会检测到M:N活动关系并失败。
原因是Play的explicit save,您必须告诉系统保存的更改,这与Hibernate(JPA)工作的“默认”方式不同,其中对象自动提交(沿交易结束时的变化。