2014-11-05 6 views
0

Моя модель выглядит следующим образом (в реальном случае есть методы получение и установка):Слияния отдельностоящий объект удаляет ребенок

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); ther bar.bazes поля имеют значение null, а после em.merge bazes удаляются из базы данных.

ответ

0

Метод attachBars никогда не должен менять ссылку на this.bars. Это было бы/arleady, созданное с помощью Hibernate, потому что мы получили foo через find(), то есть сеанс Hibernate. Ссылка на эту коллекцию, очень важна, becuase только таким образом мы можем рассчитывать на соответствующем грязные проверках (недавно добавленные, удаленные элементы)

Так оно и должно быть, как это (ожидающей коллекция была реализованной по 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; 
    } 
} 

Но в этом случае этого не должно быть достаточно. Пропущенный коллектив bars исходит от отдельных объектов. Которая не заселена bazes.

После того, как они будут снова привязаны к только что загруженному объекту, у них могут быть пустые коллекции. Поэтому перед тем, как мы отделим корневой объект, мы также должны принудительно инициализировать все экземпляры Baz.

Даже лучшее решение, я хотел бы предложить, чтобы перебирать старую коллекцию баров и нагрузки по идентификатору фактические прокси

+0

С дополнительным bars.clear(), но хорошо. Я проверю, была ли эта проблема. – Krever

Смежные вопросы