我有这样一个问题:

org.hibernate.LazyInitializationException:惰性初始化role: mvc3.model.Topic.comments集合失败,没有会话或会话已关闭

下面是模型:

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

}

调用model的控制器如下所示:

@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的最好方法是在查询时加入取回,像这样:

select t
from Topic t
left join fetch t.comments

您应该始终避免以下反模式:

FetchType。急切的 OSIV (Open Session in View) 冬眠。enable_lazy_load_no_trans Hibernate配置属性

因此,确保你的FetchType。LAZY关联在查询时或使用Hibernate在原始的@Transactional范围内初始化。初始化辅助集合。

其他回答

对于那些使用Criteria的人,我发现

criteria.setFetchMode("lazily_fetched_member", FetchMode.EAGER);

我该做的都做了

集合的初始获取模式设置为FetchMode。LAZY提供性能,但当我需要数据时,我只需要添加这一行,并享受完全填充的对象。

我知道这是个老问题,但我想帮忙。 可以将事务注释放在所需的服务方法上,在本例中findTopicByID(id)应该具有

@Transactional(propagation=Propagation.REQUIRED, readOnly=true, noRollbackFor=Exception.class)

关于这个注释的更多信息可以在这里找到

关于其他解决方案:

fetch = FetchType.EAGER 

这不是一个好的做法,只有在必要时才应该使用。

Hibernate.initialize(topics.getComments());

hibernate初始化器将类绑定到hibernate技术。如果你的目标是灵活并不是一个好方法。

希望能有所帮助

此问题是由于在关闭hibernate会话的情况下访问属性造成的。控制器中没有hibernate事务。

可能的解决方式:

Do all this logic, in the service layer, (with the @Transactional), not in the controller. There should be the right place to do this, it is part of the logic of the app, not in the controller (in this case, an interface to load the model). All the operations in the service layer should be transactional. i.e.: Move this line to the TopicService.findTopicByID method: Collection commentList = topicById.getComments(); Use 'eager' instead of 'lazy'. Now you are not using 'lazy' .. it is not a real solution, if you want to use lazy, works like a temporary (very temporary) workaround. use @Transactional in the Controller. It should not be used here, you are mixing service layer with presentation, it is not a good design. use OpenSessionInViewFilter, many disadvantages reported, possible instability.

一般来说,最佳解是1。

处理LazyInitializationException的最好方法是在查询时加入取回,像这样:

select t
from Topic t
left join fetch t.comments

您应该始终避免以下反模式:

FetchType。急切的 OSIV (Open Session in View) 冬眠。enable_lazy_load_no_trans Hibernate配置属性

因此,确保你的FetchType。LAZY关联在查询时或使用Hibernate在原始的@Transactional范围内初始化。初始化辅助集合。

如果你试图在一个实体和一个集合或java对象的列表(例如长类型)之间有一个关系,它会像这样:

@ElementCollection(fetch = FetchType.EAGER)
    public List<Long> ids;