0

In my controller I have the following code getting a specific presentation in my database, adding it as a model-attribute and returning the detail view:

@RequestMapping(value = "/detail", method = RequestMethod.GET)
public String detail(Model model, Principal principal, @RequestParam("id") int id) {
        Presentation p = presentationDao.get(id);
        model.addAttribute("presentation", p);
        return "detail";
}

In my view I'm trying to display an attribute of the Presentation that has lazy loading using JSTL:

${pressentation.student.dossiers.proposal.titel}

However in Student there is a list of 'Dossiers', but it is using Lazy Loading:

@OneToMany(mappedBy = "student", fetch = FetchType.LAZY)
private List<Dossier> dossiers;

but I get the following exception:

org.apache.jasper.JasperException: javax.el.ELException: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: domein.Student.dossiers, no session or session was closed

When I set FetchType of dossiers to Eager I can't even run my project:

Severe:   Exception while loading the app : java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in ServletContext resource [/WEB-INF/dispatcher-servlet.xml]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build EntityManagerFactory

When I googled I found the following solution:

@RequestMapping(value = "/detail", method = RequestMethod.GET)
    public String detail(Model model, Principal principal, @RequestParam("id") int id) { 
        Presentatie p = presentatieDao.get(id);
        Hibernate.initialize(p.getStudent().getDefinitiefDossier().getVoorstel().getTitel());
        model.addAttribute("presentatie", p);
        return "detail";
}

but it's giving me the follow exception again:

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: domein.Student.dossiers, no session or session was closed
Jelle Elaut
  • 17
  • 1
  • 7

2 Answers2

1

Your controller does not have the context with database, so that it is not possible for him to get all the Lazy Loading data. What you need to do is to write a method directly in your Model object (probably presentatieDao DAO) and add all elements to the list from this method, before getting it in the controller.

TheMP
  • 8,257
  • 9
  • 44
  • 73
  • Nice! I didn't think about that. I'm using the following method in my PresentatieDao: public Presentatie get(int id) { return em.find(Presentatie.class, id); } where em is my EntityManager – Jelle Elaut May 19 '14 at 16:20
  • I don't really know what to add to my method in the PresentatieDao. Do you have any idea? I just use the find method from EntityManager.. – Jelle Elaut May 19 '14 at 16:26
  • The view code is out of the session and transactional boundaries so it cannot lazily load the data. The data should probably be eagerly loaded if you know it will be needed on every request. So I think the focus should be on figuring out why using eager loading failed. – jordan May 19 '14 at 16:44
  • Yeah, but I don't get any information why eager loading isn't working except that my EntityManagerFactory can't be created.. – Jelle Elaut May 19 '14 at 16:47
  • By using em.find you return your single entity, but the list variables within it are still not initiated. Either change your FetchType to EAGER (the easier way) or Presentatie myEntity=em.find(Presentatie.class, id) and then try to use Hibernate.initialize(myEntity.getDefinitiefDossier()); – TheMP May 19 '14 at 16:47
  • When I try this I get the following error again: nested exception is org.hibernate.LazyInitializationException: could not initialize proxy - no Session – Jelle Elaut May 19 '14 at 17:03
0

You have many options:

  1. you make the collection EAGER
  2. you create another DAO method and you call it presentatieDao.getWithDossiers(id), where you do something to make it load the dossiers (like .size() on the dossiers collection).
  3. You mark the controller method as @Transactional, this will cause the Session to remain opened and will fetch it properly (but may slow down your app in the long run).

Another one:

  1. Try open session in view interceptor http://springtips.blogspot.co.uk/2007/07/open-session-in-view.html
gotch4
  • 13,093
  • 29
  • 107
  • 170
  • Making the collection eager gives me a 'Unable to build EntityManagerFactory' Your other solutions give me the following error: 'org.hibernate.LazyInitializationException: could not initialize proxy - no Session' So tired of it :P – Jelle Elaut May 19 '14 at 17:11