从关系

时间:2015-08-15 15:59:15

标签: java hibernate cascade

我自己做了一个小的休眠沙箱来理解它是如何工作的。 到目前为止,我已经完成了所有基础知识。一切都按预期工作。 我只有一个未解决的问题。

为了缩短它,我有一个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了解如何做到这一点。 所以我以后可以通过多对多的关系找到自己的方式(我想它会非常相似)。

提前谢谢。

2 个答案:

答案 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);
    }

这样,我的病在会话中是最新的,我不需要刷新会话。

这会是个好主意吗? 关于性能方面,我认为覆盖解决方案会生成可能不需要的额外数据库操作吗?