Hibernate: нет сеанса после сохранения нового объекта - PullRequest
2 голосов
/ 03 апреля 2012

Я создаю новый объект, сохраняю его в первый раз, а затем хочу получить доступ к коллекциям связанных классов:

 @Override
 protected void onSubmit(final AjaxRequestTarget target, final Form<?> form) {           
        final E entity = (E) form.getModelObject();
        getDao().save(entity); //calls session.saveOrUpdate(entity)
        LOG.debug("Saved entity " + entity);
        LOG.debug("Show collections " + entity.getField().getListOfSomething());
        parent.replaceContentPanel(parent.getDetailsPanel(parent.createReloadableModel(entity)), target);
 }

Я получаю следующую ошибку во второй строке журнала:

org.hibernate.LazyInitializationException: 
failed to lazily initialize a collection of role: 
no session or session was closed

Я тоже пробовал

Hibernate.initialize(getDetailsModel().getObject().getField().getListOfSomething());

Это приводит к другой ошибке:

org.hibernate.HibernateException: collection is not associated with any session

Это не очень удивительно при отладке. Я вижу, что у прокси-серверов коллекций нет связанных с ними сеансов.

Я использую фильтр 'openSessionInView', который поставляется с платформой Spring. Код прекрасно работает, кстати, когда я хочу обновить существующую сущность. Это также работает, когда я устанавливаю fetchType на коллекцию:

@OneToMany(mappedBy = "field", fetch = FetchType.EAGER)
private List<E> listOfSomething= new ArrayList<E>();

Мне действительно нужно установить это значение в EAGER? Я очень хочу этого избежать и надеялся обойти это. Есть ли способ связать вновь сохраненную сущность с сеансом Hibernate? Я пробовал и session.load(entity), и session.merge(entity), но безуспешно.

Мои сущности выглядят так:

@Entity class A { 
    @ManyToOne B b;
}

@Entity class B {     
   @OneToMany(mappedBy = "b") List<A> aList;
   @OneToMany(mappedBy = "b") List<C> cList;
}

@Entity class C {
   @ManyToOne B b;
}

Я создаю c = new C(), выбираю b из DropDownChoice и при отправке хочу сохранить getDao().save(c). После отправки я хочу отобразить мою новую сущность на другой панели, которая загружается через ajax. Например, я хочу отобразить c.getB().getAList(), и именно здесь происходит исключение, потому что b, выбранный из DropdownChoice, является отсоединенным объектом, и его aList не было получено и также не может быть загружено лениво.

Я не могу понять, как вставить все еще существующий сеанс в мой новый экземпляр C.

Вот больше информации от моего web.xml

<filter>
    <filter-name>opensessioninview</filter-name>
    <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>        
</filter>
<filter-mapping>
    <filter-name>opensessioninview</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

Ответы [ 2 ]

0 голосов
/ 03 апреля 2012

Я нашел обходной путь, который позволяет мне принудительно загружать коллекции, которые, как я знаю, мне понадобятся, с помощью Hibernate.initialize(...)

final ListModel<B> listModel = new ListModel<B>(bList);
for (final B b : bList) {
   Hibernate.initialize(b.getAList());
}
add(new DropDownChoice<B>("b", listModel, new ChoiceRenderer<B>("name", "id")));

Когда я добавляю строки 2-4 из этого фрагмента в мою форму для всех экземпляровB, который я мог бы позже выбрать для моего нового экземпляра C, будет иметь инициализированный список A.

Я доволен этим только наполовину.Я бы все же предпочел иметь возможность прикреплять объект к сеансу гибернации по требованию.

0 голосов
/ 03 апреля 2012

Подходящим обходным путем является слияние () объекта, содержащего коллекцию, перед доступом к коллекции.

...