我有这样一个问题:

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循环的行中


当前回答

还有另一种方法,可以使用TransactionTemplate封装惰性获取。 就像

Collection<Comment> commentList = this.transactionTemplate.execute
(status -> topicById.getComments());

其他回答

如果你知道你想在每次检索主题时看到所有的注释,那么将注释的字段映射更改为:

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

默认情况下,集合是惰性加载的,如果你想了解更多,可以看看这个。

此问题是由于在关闭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。

这是我最近遇到的问题,我用

<f:attribute name="collectionType" value="java.util.ArrayList" />

这里有更详细的描述,这挽救了我的一天。

在第二次执行生成JWT令牌的方法后,我得到了这个错误。

line user.getUsersRole().stream().forEachOrdered((ur) -> roles.add(ur. getroleid ()));生成错误。

// MyUserDetails.java

@Service
public class MyUserDetails implements UserDetailsService {

  @Override
  public UserDetails loadUserByUsername(String email) {

    /* ERROR
    /* org.hibernate.LazyInitializationException: failed to 
    /* lazily initialize a collection of role: 
    /* com.organizator.backend.model.User.usersRole, 
    /* could not initialize proxy - no Session */
    user.getUsersRole().stream().forEachOrdered((ur) ->
           roles.add(ur.getRoleId()));

在我的例子中,@Transactional注释解决了它,

// MyUserDetails.java

import org.springframework.transaction.annotation.Transactional;

@Service
public class MyUserDetails implements UserDetailsService {

  @Override
  @Transactional // <-- added
  public UserDetails loadUserByUsername(String email) {

    /* No Error */
    user.getUsersRole().stream().forEachOrdered((ur) ->
           roles.add(ur.getRoleId()));

原因是当您使用延迟加载时,会话是关闭的。

有两种解决方案。

不要使用惰性加载。 在XML中设置lazy=false或在注释中设置@OneToMany(fetch = FetchType.EAGER)。 使用惰性加载。 在XML中设置lazy=true或在注释中设置@OneToMany(fetch = FetchType.LAZY)。 并在web.xml中添加OpenSessionInViewFilter过滤器

详见我的帖子。