Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to solve the “failed to lazily initialize a collection of role” Hibernate exception

I have this problem:

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: mvc3.model.Topic.comments, no session or session was closed

Here is the model:

@Entity @Table(name = "T_TOPIC") public class Topic {      @Id     @GeneratedValue(strategy=GenerationType.AUTO)     private int id;      @ManyToOne     @JoinColumn(name="USER_ID")     private User author;      @Enumerated(EnumType.STRING)         private Tag topicTag;      private String name;     private String text;      @OneToMany(mappedBy = "topic", cascade = CascadeType.ALL)     private Collection<Comment> comments = new LinkedHashSet<Comment>();      ...      public Collection<Comment> getComments() {            return comments;     }  } 

The controller, which calls model looks like the following:

@Controller @RequestMapping(value = "/topic") public class TopicController {      @Autowired     private TopicService service;      private static final Logger logger = LoggerFactory.getLogger(TopicController.class);       @RequestMapping(value = "/details/{topicId}", method = RequestMethod.GET)     public ModelAndView details(@PathVariable(value="topicId") int id)     {              Topic topicById = service.findTopicByID(id);             Collection<Comment> commentList = topicById.getComments();              Hashtable modelData = new Hashtable();             modelData.put("topic", topicById);             modelData.put("commentList", commentList);              return new ModelAndView("/topic/details", modelData);       }  } 

The jsp-page looks li the following:

<%@page import="com.epam.mvc3.helpers.Utils"%> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <%@ page session="false" %> <html> <head>       <title>View Topic</title> </head> <body>  <ul> <c:forEach items="${commentList}" var="item"> <jsp:useBean id="item" type="mvc3.model.Comment"/> <li>${item.getText()}</li>  </c:forEach> </ul> </body> </html> 

Exception is rised, when viewing jsp. In the line with c:forEach loop

like image 634
Eugene Avatar asked Jul 31 '12 18:07

Eugene


People also ask

How do I fix lazy initialization exception?

The right way to fix a LazyInitializationException is to fetch all required associations within your service layer. The best option for that is to load the entity with all required associations in one query.

Can't initialize proxy no session Hibernate Java?

LazyInitializationException: could not initialize proxy - no Session in Hibernate". Why this error comes, because hibernate needs to go database to initialize the proxy object, and the connection is already closed.


2 Answers

If you know that you'll want to see all Comments every time you retrieve a Topic then change your field mapping for comments to:

@OneToMany(fetch = FetchType.EAGER, mappedBy = "topic", cascade = CascadeType.ALL) private Collection<Comment> comments = new LinkedHashSet<Comment>(); 

Collections are lazy-loaded by default, take a look at this if you want to know more.

like image 89
darrengorman Avatar answered Oct 18 '22 22:10

darrengorman


From my experience, I have the following methods to solved the famous LazyInitializationException:

(1) Use Hibernate.initialize

Hibernate.initialize(topics.getComments()); 

(2) Use JOIN FETCH

You can use the JOIN FETCH syntax in your JPQL to explicitly fetch the child collection out. This is some how like EAGER fetching.

(3) Use OpenSessionInViewFilter

LazyInitializationException often occur in view layer. If you use Spring framework, you can use OpenSessionInViewFilter. However, I do not suggest you to do so. It may leads to performance issue if not use correctly.

like image 34
Boris Avatar answered Oct 18 '22 23:10

Boris