合并分离的对象会删除子对象

时间:2014-11-05 13:49:25

标签: hibernate

我的模型看起来像这样(在实际情况下有吸气剂和制定者):

class Foo {
    Set<Bar> bars; 

    void attachBars(Set<Bar> bars){
        this.bars = bars;
        for(Bar bar : bars)
            bar.foo = this;
    }
}
class Bar {
    Set<Baz> bazes;  
}
class Baz {
}

然后我执行:

Foo foo = e.find(Foo.class, "id");
Hibernate.initialize(foo.bars);
em.detach(foo)

Foo foo2 = e.find(Foo.class, "id");
doSomeChanges(foo2);
foo2.attachBars(foo.bars);

我在调试器中看到的内容:

attachBars(foo.bars);之前

bar.bazes

无法访问LazyInitializationException字段

attachBars(foo.bars); bar.bazes个字段设置为null后,在em.merge之后,将从数据库中删除bazes。

1 个答案:

答案 0 :(得分:0)

attachBars方法永远不应更改对this.bars的引用。它将被 Hibernate 实例化,因为我们通过find(),即Hibernate会话来重新获取foo。引用此集合是必不可少的,因为只有这样我们才能依赖正确的脏检查(新添加,删除的项目)

所以它应该是这样的(期望集合由Hibernate实例化)

void attachBars(Set<Bar> bars){
    if(this.bars == null){
      this.bars = new HashSet<Bar>();
    }
    for(Bar bar : bars){
        this.bars.add(bar);
        bar.foo = this;
    }
}

但在这种情况下,这还不够。传递的colleciton bars来自分离的对象。其中没有填充bazes集合。

一旦将它们重新分配到刚刚加载的对象,它们似乎就有了空集合。因此,在我们分离根对象之前,我们应该强制所有Baz实例的初始化。

更好的解决方案,我建议迭代旧的条形集合并通过id加载实际的代理