我自己做了一个小的休眠沙箱来理解它是如何工作的。 到目前为止,我已经完成了所有基础知识。一切都按预期工作。 我只有一个未解决的问题。
为了缩短它,我有一个Rats实体和一个Sickness实体。 老鼠可以有一个病。 关联已正确设置到DB中,实体文件包含此部分:
在Rats课程中: [...]
@ManyToOne(fetch = FetchType.LAZY )
@Cascade({ CascadeType.SAVE_UPDATE, CascadeType.DELETE})
@JoinColumn(name = "Sickness_Id")
public Sickness getSickness() {
return this.sickness;
}
[...]
在疾病类: [...]
@OneToMany(fetch = FetchType.LAZY, mappedBy = "sickness")
@Cascade({ /*CascadeType.SAVE_UPDATE,*/ CascadeType.MERGE, CascadeType.REFRESH})
public Set<Rats> getRatses() {
return this.ratses;
}
[...]
如果我创建一个具有新疾病的新老鼠并保存大鼠,则级联按预期工作,并且疾病也会自动添加到数据库中。 删除部分也有效,当我删除一只老鼠时,它的病情就会被删除。
什么行不通的是试图创建一个疾病,并尝试通过其SetRatses方法将其传播给许多老鼠:
String sick_name2 = "Tourista";
System.out.println("\nsetting new sickness: " + sick_name2 + " and assigning it to all rats");
Sickness sickness2 = new Sickness();
sickness2.setNom(sick_name2);
ArrayList<Rats> sickratsList = (ArrayList<Rats>) session.createCriteria(Rats.class).list();// new HashSet<Rats>();
Set<Rats> sickRatsSet = new HashSet<Rats>();
for(Rats rat : sickratsList){
sickRatsSet.add(rat);
}
sickness2.setRatses(sickRatsSet);
session.save(sickness2);
显示这表明疾病正确插入DB,其sickRatsSet字段与所有老鼠正确设置。 但是......如果我检查老鼠状态,他们的疾病还没有更新。
尝试设置CascadeType。进入疾病关系并没有帮助。
我知道我可以通过以下方式解决它:
ArrayList<Rats> sickratsList = (ArrayList<Rats>) session.createCriteria(Rats.class).list();// new HashSet<Rats>();
Set<Rats> sickRatsSet = new HashSet<Rats>();
for(Rats rat : sickratsList){
rat.setSickness(seckness2);
session.save(rat);
}
但我想通过Sickness.setRatses了解如何做到这一点。 所以我以后可以通过多对多的关系找到自己的方式(我想它会非常相似)。
提前谢谢。答案 0 :(得分:2)
双向关联具有所有者方(没有 mappedBy
属性的一方)和反向方(支持 mappedBy
属性。
在决定哪些实体彼此关联时,Hibernate仅考虑所有者方面。
将老鼠添加到疾病中因此不会使Hibernate将大鼠与疾病相关联,因为这只会改变反面。你必须设定老鼠的疾病。
请注意,在ManyToXxx注释上使用DELETE级联并没有多大意义。一旦拥有旅游者的一千只老鼠中的一只被删除,就没有理由从数据库中删除旅游者的疾病。不管怎样,这显然会引起异常,因为其他999只老鼠都有传染病的外键。
答案 1 :(得分:0)
感谢JB和Augusto,我现在得到了更好的理解。
我能够通过这种方式解决我的问题:
public void setRatses(Set<Rats> ratses) {
this.ratses = ratses;
for(Rats rat : ratses){
rat.setSickness(this);
}
这给我带来了另一个方法论问题。
我发现如果我执行以下操作: raton.setSickness(sickness1); raton.display(); - &GT; raton.sickness = sickness1如预期的那样 sickness1.display(); - &GT; sickness1.ratses不包含raton因为你们指出的原因。
我可以使用session.flush() session.clear()或提交事务,如果我需要sickness1.ratses是最新的,就开始一个新事务。
我想我也可以用这种方式覆盖Rats.setSickness:
public void setSickness(Sickness sickness) {
if(sickness.ratses.contain(this) sickness.ratses.remove(this);
this.sickness = sickness;
ickness.ratses.add(this);
}
这样,我的病在会话中是最新的,我不需要刷新会话。
这会是个好主意吗? 关于性能方面,我认为覆盖解决方案会生成可能不需要的额外数据库操作吗?