2

I create a new entity, store it the first time and then want to access the collections of the related classes:

 @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);
 }

I get the following error on the second line of logging:

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

I have also tried

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

This leads to a different error:

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

This is not very surprising when debugging I can see that the collection proxies have no session associated with them.

I am using the 'openSessionInView' filter that comes with the Spring framework. The code works fine by the way when I want to update an existing entity. It also works when I set the fetchType to eager on the collection:

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

Do I really need to set this to EAGER? I want to avoid this very much and was hoping for a way around it. Is there a way to associate a newly stored entity with the Hibernate session? I have tried both a session.load(entity) and a session.merge(entity) with no success.

My entities look like this:

@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;
}

What I am doing is creating a c = new C(), selecting b from a DropDownChoice and on submit I want to persist getDao().save(c). After the submit I want to display my new entity on a different panel which is loaded via ajax. For example I want to display c.getB().getAList() and that is where the exception happens because the bI selected from the DropdownChoiceis a detached entity and it's aList was not fetched and cannot be loaded lazily either.

I cannot figure out how to get the still existing session into my new C instance.

Here's more info from my 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>
7
  • The 'openSessionInView'-filter you're using, when/where does the transaction start and commit?
    – rotsch
    Commented Apr 3, 2012 at 7:26
  • How does your Entity look like? E.g. does the save operation cascade to the collection?
    – bert
    Commented Apr 3, 2012 at 8:32
  • Please include relevant parts of your web.xml (dispatcher servlet and OpenSessionInView filter)
    – pap
    Commented Apr 3, 2012 at 14:00
  • What IModel implementation are you using to hold the entity? Have you tried to use a LoadableDetachableModel?
    – tetsuo
    Commented Apr 3, 2012 at 19:18
  • I am using a LoadableDetachableModel (my own implementation mostly inspired by 'Wicket in Action') in combination with a CompoundPropertyModel
    – Yashima
    Commented Apr 3, 2012 at 20:45

2 Answers 2

-1

An appropriate workaround is to merge() the object that contains the collection before accessing the collection.

1
  • I tried merging the original entity, I tried merging just the related one that contains the collection. neither works -.-
    – Yashima
    Commented Apr 3, 2012 at 12:39
-1

I found a work-around that allows me to enforce loading the collections I know I will need with 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")));

When I add lines 2-4 from this snippet to my form all instances of B that I might later select for my new instance of C will have an initialized list of A.

I am only half happy with this. I'd still prefer to be able to attach an object to the hibernate session on demand.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.