我有这个问题:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: mvc3.model.Topic.comments, no session or session was closed
这是模型:
@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; } }
调用模型的控制器如下所示:
@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); } }
jsp页看起来如下所示:
<%@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>
查看jsp时会引发异常。与c:forEach循环一致
根据我的经验,我有以下方法来解决著名的LazyInitializationException:
(1)使用Hibernate.initialize
Hibernate.initialize(topics.getComments());
(2)使用JOIN FETCH
你可以在JPQL中使用JOIN FETCH语法来显式提取子集合。这有点像EAGER提取。
(3)使用OpenSessionInViewFilter
LazyInitializationException经常在视图层中发生。如果使用Spring框架,则可以使用OpenSessionInViewFilter。但是,我不建议你这样做。如果使用不正确,可能会导致性能问题。